mirror of
https://github.com/vanitasvitae/Smack.git
synced 2025-09-12 02:29:38 +02:00
Normalize newlines to '\n'
Change all \r\n into unix style newlines. Add missing newlines at the end of a file and activate the newline checkstyle module, that enforces '\n' as newline and a newline at the end of every file.
This commit is contained in:
parent
1e57f1c659
commit
d069e1be64
364 changed files with 50349 additions and 50346 deletions
|
@ -64,4 +64,4 @@ import org.jivesoftware.smackx.packet.JingleError;
|
|||
public JingleError getError() {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -595,4 +595,4 @@ public class JingleManager implements JingleSessionListener {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jivesoftware.smackx.jingle.listeners;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
|
||||
/**
|
||||
* Inteface used to dispatch a event when a Jingle session is created.
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public interface CreatedJingleSessionListener {
|
||||
|
||||
public void sessionCreated(JingleSession jingleSession);
|
||||
|
||||
}
|
||||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jivesoftware.smackx.jingle.listeners;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
|
||||
/**
|
||||
* Inteface used to dispatch a event when a Jingle session is created.
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public interface CreatedJingleSessionListener {
|
||||
|
||||
public void sessionCreated(JingleSession jingleSession);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,48 +1,48 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.listeners;
|
||||
|
||||
/**
|
||||
* Interface for listening to jmf info events.
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public interface JingleMediaInfoListener extends JingleListener {
|
||||
/**
|
||||
* The other end is busy.
|
||||
*/
|
||||
public void mediaInfoBusy();
|
||||
|
||||
/**
|
||||
* We are on hold.
|
||||
*/
|
||||
public void mediaInfoHold();
|
||||
|
||||
/**
|
||||
* The jmf is muted.
|
||||
*/
|
||||
public void mediaInfoMute();
|
||||
|
||||
/**
|
||||
* We are queued.
|
||||
*/
|
||||
public void mediaInfoQueued();
|
||||
|
||||
/**
|
||||
* We are ringing.
|
||||
*/
|
||||
public void mediaInfoRinging();
|
||||
}
|
||||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.listeners;
|
||||
|
||||
/**
|
||||
* Interface for listening to jmf info events.
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public interface JingleMediaInfoListener extends JingleListener {
|
||||
/**
|
||||
* The other end is busy.
|
||||
*/
|
||||
public void mediaInfoBusy();
|
||||
|
||||
/**
|
||||
* We are on hold.
|
||||
*/
|
||||
public void mediaInfoHold();
|
||||
|
||||
/**
|
||||
* The jmf is muted.
|
||||
*/
|
||||
public void mediaInfoMute();
|
||||
|
||||
/**
|
||||
* We are queued.
|
||||
*/
|
||||
public void mediaInfoQueued();
|
||||
|
||||
/**
|
||||
* We are ringing.
|
||||
*/
|
||||
public void mediaInfoRinging();
|
||||
}
|
||||
|
|
|
@ -1,40 +1,40 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jivesoftware.smackx.jingle.listeners;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.media.PayloadType;
|
||||
|
||||
/**
|
||||
* Interface for listening to jmf events.
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public interface JingleMediaListener extends JingleListener {
|
||||
/**
|
||||
* Notification that the jmf has been negotiated and established.
|
||||
*
|
||||
* @param pt The payload type agreed.
|
||||
*/
|
||||
public void mediaEstablished(PayloadType pt);
|
||||
|
||||
/**
|
||||
* Notification that a payload type must be cancelled
|
||||
*
|
||||
* @param cand The payload type that must be closed
|
||||
*/
|
||||
public void mediaClosed(PayloadType cand);
|
||||
}
|
||||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jivesoftware.smackx.jingle.listeners;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.media.PayloadType;
|
||||
|
||||
/**
|
||||
* Interface for listening to jmf events.
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public interface JingleMediaListener extends JingleListener {
|
||||
/**
|
||||
* Notification that the jmf has been negotiated and established.
|
||||
*
|
||||
* @param pt The payload type agreed.
|
||||
*/
|
||||
public void mediaEstablished(PayloadType pt);
|
||||
|
||||
/**
|
||||
* Notification that a payload type must be cancelled
|
||||
*
|
||||
* @param cand The payload type that must be closed
|
||||
*/
|
||||
public void mediaClosed(PayloadType cand);
|
||||
}
|
||||
|
|
|
@ -1,82 +1,82 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.listeners;
|
||||
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
import org.jivesoftware.smackx.jingle.media.PayloadType;
|
||||
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
|
||||
|
||||
/**
|
||||
* Interface for listening for session events.
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public interface JingleSessionListener extends JingleListener {
|
||||
/**
|
||||
* Notification that the session has been established. Arguments specify
|
||||
* the payload type and transport to use.
|
||||
*
|
||||
* @param pt the Payload tyep to use
|
||||
* @param remoteCandidate the remote candidate to use for connecting to the remote
|
||||
* service.
|
||||
* @param localCandidate the local candidate where we must listen for connections
|
||||
* @param jingleSession Session that called the method
|
||||
*/
|
||||
public void sessionEstablished(PayloadType pt, TransportCandidate remoteCandidate,
|
||||
TransportCandidate localCandidate, JingleSession jingleSession);
|
||||
|
||||
/**
|
||||
* Notification that the session was declined.
|
||||
*
|
||||
* @param reason the reason (if any).
|
||||
* @param jingleSession Session that called the method
|
||||
*/
|
||||
public void sessionDeclined(String reason, JingleSession jingleSession);
|
||||
|
||||
/**
|
||||
* Notification that the session was redirected.
|
||||
*
|
||||
* @param redirection
|
||||
* @param jingleSession session that called the method
|
||||
*/
|
||||
public void sessionRedirected(String redirection, JingleSession jingleSession);
|
||||
|
||||
/**
|
||||
* Notification that the session was closed normally.
|
||||
*
|
||||
* @param reason the reason (if any).
|
||||
* @param jingleSession Session that called the method
|
||||
*/
|
||||
public void sessionClosed(String reason, JingleSession jingleSession);
|
||||
|
||||
/**
|
||||
* Notification that the session was closed due to an exception.
|
||||
*
|
||||
* @param e the exception.
|
||||
* @param jingleSession session that called the method
|
||||
*/
|
||||
public void sessionClosedOnError(XMPPException e, JingleSession jingleSession);
|
||||
|
||||
/**
|
||||
* Notification that the Media has arrived for this session.
|
||||
*
|
||||
* @param jingleSession session that called the method
|
||||
* @param participant description of the participant
|
||||
*/
|
||||
public void sessionMediaReceived(JingleSession jingleSession, String participant);
|
||||
|
||||
}
|
||||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.listeners;
|
||||
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
import org.jivesoftware.smackx.jingle.media.PayloadType;
|
||||
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
|
||||
|
||||
/**
|
||||
* Interface for listening for session events.
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public interface JingleSessionListener extends JingleListener {
|
||||
/**
|
||||
* Notification that the session has been established. Arguments specify
|
||||
* the payload type and transport to use.
|
||||
*
|
||||
* @param pt the Payload tyep to use
|
||||
* @param remoteCandidate the remote candidate to use for connecting to the remote
|
||||
* service.
|
||||
* @param localCandidate the local candidate where we must listen for connections
|
||||
* @param jingleSession Session that called the method
|
||||
*/
|
||||
public void sessionEstablished(PayloadType pt, TransportCandidate remoteCandidate,
|
||||
TransportCandidate localCandidate, JingleSession jingleSession);
|
||||
|
||||
/**
|
||||
* Notification that the session was declined.
|
||||
*
|
||||
* @param reason the reason (if any).
|
||||
* @param jingleSession Session that called the method
|
||||
*/
|
||||
public void sessionDeclined(String reason, JingleSession jingleSession);
|
||||
|
||||
/**
|
||||
* Notification that the session was redirected.
|
||||
*
|
||||
* @param redirection
|
||||
* @param jingleSession session that called the method
|
||||
*/
|
||||
public void sessionRedirected(String redirection, JingleSession jingleSession);
|
||||
|
||||
/**
|
||||
* Notification that the session was closed normally.
|
||||
*
|
||||
* @param reason the reason (if any).
|
||||
* @param jingleSession Session that called the method
|
||||
*/
|
||||
public void sessionClosed(String reason, JingleSession jingleSession);
|
||||
|
||||
/**
|
||||
* Notification that the session was closed due to an exception.
|
||||
*
|
||||
* @param e the exception.
|
||||
* @param jingleSession session that called the method
|
||||
*/
|
||||
public void sessionClosedOnError(XMPPException e, JingleSession jingleSession);
|
||||
|
||||
/**
|
||||
* Notification that the Media has arrived for this session.
|
||||
*
|
||||
* @param jingleSession session that called the method
|
||||
* @param participant description of the participant
|
||||
*/
|
||||
public void sessionMediaReceived(JingleSession jingleSession, String participant);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.listeners;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.JingleSessionRequest;
|
||||
|
||||
/**
|
||||
* Interface to listener Jingle session requests.
|
||||
*
|
||||
* @author Alvaro Saurin
|
||||
*/
|
||||
public interface JingleSessionRequestListener extends JingleListener {
|
||||
/**
|
||||
* A request to start a session has been recieved from another user.
|
||||
*
|
||||
* @param request The request from the other user.
|
||||
*/
|
||||
public void sessionRequested(JingleSessionRequest request);
|
||||
}
|
||||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.listeners;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.JingleSessionRequest;
|
||||
|
||||
/**
|
||||
* Interface to listener Jingle session requests.
|
||||
*
|
||||
* @author Alvaro Saurin
|
||||
*/
|
||||
public interface JingleSessionRequestListener extends JingleListener {
|
||||
/**
|
||||
* A request to start a session has been recieved from another user.
|
||||
*
|
||||
* @param request The request from the other user.
|
||||
*/
|
||||
public void sessionRequested(JingleSessionRequest request);
|
||||
}
|
||||
|
|
|
@ -1,55 +1,55 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.listeners;
|
||||
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
|
||||
|
||||
/**
|
||||
* Interface for listening to transport events.
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public interface JingleTransportListener extends JingleListener {
|
||||
|
||||
/**
|
||||
* Notification that the transport has been established.
|
||||
*
|
||||
* @param local The transport candidate that has been used for listening
|
||||
* in the local machine
|
||||
* @param remote The transport candidate that has been used for
|
||||
* transmitting to the remote machine
|
||||
*/
|
||||
public void transportEstablished(TransportCandidate local,
|
||||
TransportCandidate remote);
|
||||
|
||||
/**
|
||||
* Notification that a transport must be cancelled.
|
||||
*
|
||||
* @param cand The transport candidate that must be cancelled. A value
|
||||
* of "null" means all the transports for this session.
|
||||
*/
|
||||
public void transportClosed(TransportCandidate cand);
|
||||
|
||||
/**
|
||||
* Notification that the transport was closed due to an exception.
|
||||
*
|
||||
* @param e the exception.
|
||||
*/
|
||||
public void transportClosedOnError(XMPPException e);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.listeners;
|
||||
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
|
||||
|
||||
/**
|
||||
* Interface for listening to transport events.
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public interface JingleTransportListener extends JingleListener {
|
||||
|
||||
/**
|
||||
* Notification that the transport has been established.
|
||||
*
|
||||
* @param local The transport candidate that has been used for listening
|
||||
* in the local machine
|
||||
* @param remote The transport candidate that has been used for
|
||||
* transmitting to the remote machine
|
||||
*/
|
||||
public void transportEstablished(TransportCandidate local,
|
||||
TransportCandidate remote);
|
||||
|
||||
/**
|
||||
* Notification that a transport must be cancelled.
|
||||
*
|
||||
* @param cand The transport candidate that must be cancelled. A value
|
||||
* of "null" means all the transports for this session.
|
||||
*/
|
||||
public void transportClosed(TransportCandidate cand);
|
||||
|
||||
/**
|
||||
* Notification that the transport was closed due to an exception.
|
||||
*
|
||||
* @param e the exception.
|
||||
*/
|
||||
public void transportClosedOnError(XMPPException e);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,85 +1,85 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jivesoftware.smackx.jingle.media;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
import org.jivesoftware.smackx.jingle.nat.JingleTransportManager;
|
||||
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class provides necessary Jingle Session jmf methods and behavior.
|
||||
* <p/>
|
||||
* The goal of this class is to provide a flexible way to make JingleManager control jmf streaming APIs without implement them.
|
||||
* For instance you can implement a file transfer using java sockets or a VOIP Media Manager using JMF.
|
||||
* You can implement many JingleMediaManager according to you necessity.
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public abstract class JingleMediaManager {
|
||||
|
||||
public static final String MEDIA_NAME = "JingleMediaManager";
|
||||
|
||||
// Each media manager must keep track of the transport manager that it uses.
|
||||
private JingleTransportManager transportManager;
|
||||
|
||||
public JingleMediaManager(JingleTransportManager transportManager) {
|
||||
this.transportManager = transportManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return The transport manager that goes with this media manager.
|
||||
*/
|
||||
public JingleTransportManager getTransportManager() {
|
||||
return transportManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all supported Payloads for this Manager
|
||||
*
|
||||
* @return The Payload List
|
||||
*/
|
||||
public abstract List<PayloadType> getPayloads();
|
||||
|
||||
/**
|
||||
* Returns the Preferred PayloadType of the Media Manager
|
||||
*
|
||||
* @return The PayloadType
|
||||
*/
|
||||
public PayloadType getPreferredPayloadType() {
|
||||
return getPayloads().size() > 0 ? getPayloads().get(0) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Media Session Implementation
|
||||
*
|
||||
* @param payloadType
|
||||
* @param remote
|
||||
* @param local
|
||||
* @return
|
||||
*/
|
||||
public abstract JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote,
|
||||
final TransportCandidate local, JingleSession jingleSession);
|
||||
|
||||
// This is to set the attributes of the <content> element of the Jingle packet.
|
||||
public String getName() {
|
||||
return MEDIA_NAME;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jivesoftware.smackx.jingle.media;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
import org.jivesoftware.smackx.jingle.nat.JingleTransportManager;
|
||||
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class provides necessary Jingle Session jmf methods and behavior.
|
||||
* <p/>
|
||||
* The goal of this class is to provide a flexible way to make JingleManager control jmf streaming APIs without implement them.
|
||||
* For instance you can implement a file transfer using java sockets or a VOIP Media Manager using JMF.
|
||||
* You can implement many JingleMediaManager according to you necessity.
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public abstract class JingleMediaManager {
|
||||
|
||||
public static final String MEDIA_NAME = "JingleMediaManager";
|
||||
|
||||
// Each media manager must keep track of the transport manager that it uses.
|
||||
private JingleTransportManager transportManager;
|
||||
|
||||
public JingleMediaManager(JingleTransportManager transportManager) {
|
||||
this.transportManager = transportManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return The transport manager that goes with this media manager.
|
||||
*/
|
||||
public JingleTransportManager getTransportManager() {
|
||||
return transportManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all supported Payloads for this Manager
|
||||
*
|
||||
* @return The Payload List
|
||||
*/
|
||||
public abstract List<PayloadType> getPayloads();
|
||||
|
||||
/**
|
||||
* Returns the Preferred PayloadType of the Media Manager
|
||||
*
|
||||
* @return The PayloadType
|
||||
*/
|
||||
public PayloadType getPreferredPayloadType() {
|
||||
return getPayloads().size() > 0 ? getPayloads().get(0) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Media Session Implementation
|
||||
*
|
||||
* @param payloadType
|
||||
* @param remote
|
||||
* @param local
|
||||
* @return
|
||||
*/
|
||||
public abstract JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote,
|
||||
final TransportCandidate local, JingleSession jingleSession);
|
||||
|
||||
// This is to set the attributes of the <content> element of the Jingle packet.
|
||||
public String getName() {
|
||||
return MEDIA_NAME;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,188 +1,188 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.media;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Public Abstract Class provides a clear interface between Media Session and Jingle API.
|
||||
* <p/>
|
||||
* When a Jingle Session is fully stablished, we will have a Payload Type and two transport candidates defined for it.
|
||||
* Smack Jingle API don't implement Media Transmit and Receive methods.
|
||||
* But provides an interface to let the user implements it using another API. For instance: JMF.
|
||||
* <p/>
|
||||
* <i>The Class that implements this one, must have the support to transmit and receive the jmf.</i>
|
||||
* <i>This interface let the user choose his own jmf API.</i>
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public abstract class JingleMediaSession {
|
||||
|
||||
// Payload Type of the Session
|
||||
private PayloadType payloadType;
|
||||
// Local Transport details
|
||||
private TransportCandidate local;
|
||||
// Remote Transport details
|
||||
private TransportCandidate remote;
|
||||
// Media Locator
|
||||
private String mediaLocator;
|
||||
// Media Received Listener
|
||||
private List<MediaReceivedListener> mediaReceivedListeners = new ArrayList<MediaReceivedListener>();
|
||||
// Jingle Session
|
||||
private JingleSession jingleSession;
|
||||
|
||||
/**
|
||||
* Creates a new JingleMediaSession Instance to handle Media methods.
|
||||
*
|
||||
* @param payloadType Payload Type of the transmittion
|
||||
* @param remote Remote accepted Transport Candidate
|
||||
* @param local Local accepted Transport Candidate
|
||||
* @param mediaLocator Media Locator of the capture device
|
||||
*/
|
||||
public JingleMediaSession(PayloadType payloadType, TransportCandidate remote,
|
||||
TransportCandidate local, String mediaLocator, JingleSession jingleSession) {
|
||||
this.local = local;
|
||||
this.remote = remote;
|
||||
this.payloadType = payloadType;
|
||||
this.mediaLocator = mediaLocator;
|
||||
this.jingleSession = jingleSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the PayloadType of the Media Session
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public PayloadType getPayloadType() {
|
||||
return payloadType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Media Session local Candidate
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public TransportCandidate getLocal() {
|
||||
return local;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Media Session remote Candidate
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public TransportCandidate getRemote() {
|
||||
return remote;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the media locator or null if not defined
|
||||
*
|
||||
* @return media locator
|
||||
*/
|
||||
public String getMediaLocator() {
|
||||
return mediaLocator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the media locator
|
||||
*
|
||||
* @param mediaLocator media locator or null to use default
|
||||
*/
|
||||
public void setMediaLocator(String mediaLocator) {
|
||||
this.mediaLocator = mediaLocator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a Media Received Listener
|
||||
*
|
||||
* @param mediaReceivedListener
|
||||
*/
|
||||
public void addMediaReceivedListener(MediaReceivedListener mediaReceivedListener) {
|
||||
mediaReceivedListeners.add(mediaReceivedListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a Media Received Listener
|
||||
*
|
||||
* @param mediaReceivedListener
|
||||
*/
|
||||
public void removeMediaReceivedListener(MediaReceivedListener mediaReceivedListener) {
|
||||
mediaReceivedListeners.remove(mediaReceivedListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all Media Received Listeners
|
||||
*/
|
||||
public void removeAllMediaReceivedListener() {
|
||||
mediaReceivedListeners.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the RTP Channel preparing to transmit and receive.
|
||||
*/
|
||||
public abstract void initialize();
|
||||
|
||||
/**
|
||||
* Starts a RTP / UDP / TCP Transmission to the remote Candidate
|
||||
*/
|
||||
public abstract void startTrasmit();
|
||||
|
||||
/**
|
||||
* Starts a RTP / UDP / TCP Receiver from the remote Candidate to local Candidate
|
||||
*/
|
||||
public abstract void startReceive();
|
||||
|
||||
/**
|
||||
* Set transmit activity. If the active is true, the instance should trasmit.
|
||||
* If it is set to false, the instance should pause transmit.
|
||||
*
|
||||
* @param active
|
||||
*/
|
||||
public abstract void setTrasmit(boolean active);
|
||||
|
||||
/**
|
||||
* Stops a RTP / UDP / TCP Transmission to the remote Candidate
|
||||
*/
|
||||
public abstract void stopTrasmit();
|
||||
|
||||
/**
|
||||
* Stops a RTP / UDP / TCP Receiver from the remote Candidate to local Candidate
|
||||
*/
|
||||
public abstract void stopReceive();
|
||||
|
||||
/**
|
||||
* Called when new Media is received.
|
||||
*/
|
||||
public void mediaReceived(String participant) {
|
||||
for (MediaReceivedListener mediaReceivedListener : mediaReceivedListeners) {
|
||||
mediaReceivedListener.mediaReceived(participant);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets associated JingleSession
|
||||
* @return associated JingleSession
|
||||
*/
|
||||
public JingleSession getJingleSession() {
|
||||
return jingleSession;
|
||||
}
|
||||
}
|
||||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.media;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Public Abstract Class provides a clear interface between Media Session and Jingle API.
|
||||
* <p/>
|
||||
* When a Jingle Session is fully stablished, we will have a Payload Type and two transport candidates defined for it.
|
||||
* Smack Jingle API don't implement Media Transmit and Receive methods.
|
||||
* But provides an interface to let the user implements it using another API. For instance: JMF.
|
||||
* <p/>
|
||||
* <i>The Class that implements this one, must have the support to transmit and receive the jmf.</i>
|
||||
* <i>This interface let the user choose his own jmf API.</i>
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public abstract class JingleMediaSession {
|
||||
|
||||
// Payload Type of the Session
|
||||
private PayloadType payloadType;
|
||||
// Local Transport details
|
||||
private TransportCandidate local;
|
||||
// Remote Transport details
|
||||
private TransportCandidate remote;
|
||||
// Media Locator
|
||||
private String mediaLocator;
|
||||
// Media Received Listener
|
||||
private List<MediaReceivedListener> mediaReceivedListeners = new ArrayList<MediaReceivedListener>();
|
||||
// Jingle Session
|
||||
private JingleSession jingleSession;
|
||||
|
||||
/**
|
||||
* Creates a new JingleMediaSession Instance to handle Media methods.
|
||||
*
|
||||
* @param payloadType Payload Type of the transmittion
|
||||
* @param remote Remote accepted Transport Candidate
|
||||
* @param local Local accepted Transport Candidate
|
||||
* @param mediaLocator Media Locator of the capture device
|
||||
*/
|
||||
public JingleMediaSession(PayloadType payloadType, TransportCandidate remote,
|
||||
TransportCandidate local, String mediaLocator, JingleSession jingleSession) {
|
||||
this.local = local;
|
||||
this.remote = remote;
|
||||
this.payloadType = payloadType;
|
||||
this.mediaLocator = mediaLocator;
|
||||
this.jingleSession = jingleSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the PayloadType of the Media Session
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public PayloadType getPayloadType() {
|
||||
return payloadType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Media Session local Candidate
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public TransportCandidate getLocal() {
|
||||
return local;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Media Session remote Candidate
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public TransportCandidate getRemote() {
|
||||
return remote;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the media locator or null if not defined
|
||||
*
|
||||
* @return media locator
|
||||
*/
|
||||
public String getMediaLocator() {
|
||||
return mediaLocator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the media locator
|
||||
*
|
||||
* @param mediaLocator media locator or null to use default
|
||||
*/
|
||||
public void setMediaLocator(String mediaLocator) {
|
||||
this.mediaLocator = mediaLocator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a Media Received Listener
|
||||
*
|
||||
* @param mediaReceivedListener
|
||||
*/
|
||||
public void addMediaReceivedListener(MediaReceivedListener mediaReceivedListener) {
|
||||
mediaReceivedListeners.add(mediaReceivedListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a Media Received Listener
|
||||
*
|
||||
* @param mediaReceivedListener
|
||||
*/
|
||||
public void removeMediaReceivedListener(MediaReceivedListener mediaReceivedListener) {
|
||||
mediaReceivedListeners.remove(mediaReceivedListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all Media Received Listeners
|
||||
*/
|
||||
public void removeAllMediaReceivedListener() {
|
||||
mediaReceivedListeners.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the RTP Channel preparing to transmit and receive.
|
||||
*/
|
||||
public abstract void initialize();
|
||||
|
||||
/**
|
||||
* Starts a RTP / UDP / TCP Transmission to the remote Candidate
|
||||
*/
|
||||
public abstract void startTrasmit();
|
||||
|
||||
/**
|
||||
* Starts a RTP / UDP / TCP Receiver from the remote Candidate to local Candidate
|
||||
*/
|
||||
public abstract void startReceive();
|
||||
|
||||
/**
|
||||
* Set transmit activity. If the active is true, the instance should trasmit.
|
||||
* If it is set to false, the instance should pause transmit.
|
||||
*
|
||||
* @param active
|
||||
*/
|
||||
public abstract void setTrasmit(boolean active);
|
||||
|
||||
/**
|
||||
* Stops a RTP / UDP / TCP Transmission to the remote Candidate
|
||||
*/
|
||||
public abstract void stopTrasmit();
|
||||
|
||||
/**
|
||||
* Stops a RTP / UDP / TCP Receiver from the remote Candidate to local Candidate
|
||||
*/
|
||||
public abstract void stopReceive();
|
||||
|
||||
/**
|
||||
* Called when new Media is received.
|
||||
*/
|
||||
public void mediaReceived(String participant) {
|
||||
for (MediaReceivedListener mediaReceivedListener : mediaReceivedListeners) {
|
||||
mediaReceivedListener.mediaReceived(participant);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets associated JingleSession
|
||||
* @return associated JingleSession
|
||||
*/
|
||||
public JingleSession getJingleSession() {
|
||||
return jingleSession;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -362,4 +362,4 @@ public class PayloadType {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,287 +12,287 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.mediaimpl;
|
||||
|
||||
import java.awt.Frame;
|
||||
import java.awt.TextArea;
|
||||
import java.awt.Toolkit;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.media.Format;
|
||||
import javax.media.PlugInManager;
|
||||
import javax.media.Renderer;
|
||||
import javax.media.format.AudioFormat;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.SmackLogger;
|
||||
|
||||
import com.sun.media.ExclusiveUse;
|
||||
import com.sun.media.util.Registry;
|
||||
|
||||
public class JMFInit extends Frame implements Runnable {
|
||||
|
||||
private static final long serialVersionUID = 6476412003260641680L;
|
||||
|
||||
private static final SmackLogger LOGGER = SmackLogger.getLogger(JMFInit.class);
|
||||
|
||||
private String tempDir = "/tmp";
|
||||
|
||||
private boolean done = false;
|
||||
|
||||
private String userHome;
|
||||
|
||||
private boolean visible = false;
|
||||
|
||||
public JMFInit(String[] args, boolean visible) {
|
||||
super("Initializing JMF...");
|
||||
|
||||
this.visible = visible;
|
||||
|
||||
Registry.set("secure.allowCaptureFromApplets", true);
|
||||
Registry.set("secure.allowSaveFileFromApplets", true);
|
||||
|
||||
updateTemp(args);
|
||||
|
||||
try {
|
||||
Registry.commit();
|
||||
}
|
||||
catch (Exception e) {
|
||||
|
||||
message("Failed to commit to JMFRegistry!");
|
||||
}
|
||||
|
||||
Thread detectThread = new Thread(this);
|
||||
detectThread.run();
|
||||
|
||||
/*
|
||||
* int slept = 0; while (!done && slept < 60 * 1000 * 2) { try {
|
||||
* Thread.currentThread().sleep(500); } catch (InterruptedException ie) { }
|
||||
* slept += 500; }
|
||||
*
|
||||
* if (!done) { console.error("Detection is taking too long!
|
||||
* Aborting!"); message("Detection is taking too long! Aborting!"); }
|
||||
*
|
||||
* try { Thread.currentThread().sleep(2000); } catch
|
||||
* (InterruptedException ie) { }
|
||||
*/
|
||||
}
|
||||
|
||||
public void run() {
|
||||
detectDirectAudio();
|
||||
detectS8DirectAudio();
|
||||
detectCaptureDevices();
|
||||
done = true;
|
||||
}
|
||||
|
||||
private void updateTemp(String[] args) {
|
||||
if (args != null && args.length > 0) {
|
||||
tempDir = args[0];
|
||||
|
||||
message("Setting cache directory to " + tempDir);
|
||||
Registry r = new Registry();
|
||||
try {
|
||||
r.set("secure.cacheDir", tempDir);
|
||||
r.commit();
|
||||
|
||||
message("Updated registry");
|
||||
}
|
||||
catch (Exception e) {
|
||||
message("Couldn't update registry!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void detectCaptureDevices() {
|
||||
// check if JavaSound capture is available
|
||||
message("Looking for Audio capturer");
|
||||
Class<?> dsauto;
|
||||
try {
|
||||
dsauto = Class.forName("DirectSoundAuto");
|
||||
dsauto.newInstance();
|
||||
message("Finished detecting DirectSound capturer");
|
||||
}
|
||||
catch (ThreadDeath td) {
|
||||
throw td;
|
||||
}
|
||||
catch (Throwable t) {
|
||||
//Do nothing
|
||||
}
|
||||
|
||||
Class<?> jsauto;
|
||||
try {
|
||||
jsauto = Class.forName("JavaSoundAuto");
|
||||
jsauto.newInstance();
|
||||
message("Finished detecting javasound capturer");
|
||||
}
|
||||
catch (ThreadDeath td) {
|
||||
throw td;
|
||||
}
|
||||
catch (Throwable t) {
|
||||
message("JavaSound capturer detection failed!");
|
||||
}
|
||||
|
||||
/*
|
||||
// Check if VFWAuto or SunVideoAuto is available
|
||||
message("Looking for video capture devices");
|
||||
Class auto = null;
|
||||
Class autoPlus = null;
|
||||
try {
|
||||
auto = Class.forName("VFWAuto");
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
if (auto == null) {
|
||||
try {
|
||||
auto = Class.forName("SunVideoAuto");
|
||||
}
|
||||
catch (Exception ee) {
|
||||
|
||||
}
|
||||
try {
|
||||
autoPlus = Class.forName("SunVideoPlusAuto");
|
||||
}
|
||||
catch (Exception ee) {
|
||||
|
||||
}
|
||||
}
|
||||
if (auto == null) {
|
||||
try {
|
||||
auto = Class.forName("V4LAuto");
|
||||
}
|
||||
catch (Exception ee) {
|
||||
|
||||
}
|
||||
}
|
||||
try {
|
||||
Object instance = auto.newInstance();
|
||||
if (autoPlus != null) {
|
||||
Object instancePlus = autoPlus.newInstance();
|
||||
}
|
||||
|
||||
message("Finished detecting video capture devices");
|
||||
}
|
||||
catch (ThreadDeath td) {
|
||||
throw td;
|
||||
}
|
||||
catch (Throwable t) {
|
||||
|
||||
message("Capture device detection failed!");
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
private void detectDirectAudio() {
|
||||
Class<?> cls;
|
||||
int plType = PlugInManager.RENDERER;
|
||||
String dar = "com.sun.media.renderer.audio.DirectAudioRenderer";
|
||||
try {
|
||||
// Check if this is the Windows Performance Pack - hack
|
||||
cls = Class.forName("VFWAuto");
|
||||
// Check if DS capture is supported, otherwise fail DS renderer
|
||||
// since NT doesn't have capture
|
||||
cls = Class.forName("com.sun.media.protocol.dsound.DSound");
|
||||
// Find the renderer class and instantiate it.
|
||||
cls = Class.forName(dar);
|
||||
|
||||
Renderer rend = (Renderer) cls.newInstance();
|
||||
try {
|
||||
// Set the format and open the device
|
||||
AudioFormat af = new AudioFormat(AudioFormat.LINEAR, 44100, 16,
|
||||
2);
|
||||
rend.setInputFormat(af);
|
||||
rend.open();
|
||||
Format[] inputFormats = rend.getSupportedInputFormats();
|
||||
// Register the device
|
||||
PlugInManager.addPlugIn(dar, inputFormats, new Format[0],
|
||||
plType);
|
||||
// Move it to the top of the list
|
||||
Vector<String> rendList = PlugInManager.getPlugInList(null, null,
|
||||
plType);
|
||||
int listSize = rendList.size();
|
||||
if (rendList.elementAt(listSize - 1).equals(dar)) {
|
||||
rendList.removeElementAt(listSize - 1);
|
||||
rendList.insertElementAt(dar, 0);
|
||||
PlugInManager.setPlugInList(rendList, plType);
|
||||
PlugInManager.commit();
|
||||
// Log.debug("registered");
|
||||
}
|
||||
rend.close();
|
||||
}
|
||||
catch (Throwable t) {
|
||||
// Log.debug("Error " + t);
|
||||
}
|
||||
}
|
||||
catch (Throwable tt) {
|
||||
//Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
private void detectS8DirectAudio() {
|
||||
Class<?> cls;
|
||||
int plType = PlugInManager.RENDERER;
|
||||
String dar = "com.sun.media.renderer.audio.DirectAudioRenderer";
|
||||
try {
|
||||
// Check if this is the solaris Performance Pack - hack
|
||||
cls = Class.forName("SunVideoAuto");
|
||||
|
||||
// Find the renderer class and instantiate it.
|
||||
cls = Class.forName(dar);
|
||||
|
||||
Renderer rend = (Renderer) cls.newInstance();
|
||||
|
||||
if (rend instanceof ExclusiveUse
|
||||
&& !((ExclusiveUse) rend).isExclusive()) {
|
||||
// sol8+, DAR supports mixing
|
||||
Vector<String> rendList = PlugInManager.getPlugInList(null, null,
|
||||
plType);
|
||||
int listSize = rendList.size();
|
||||
boolean found = false;
|
||||
String rname = null;
|
||||
|
||||
for (int i = 0; i < listSize; i++) {
|
||||
rname = (String) (rendList.elementAt(i));
|
||||
if (rname.equals(dar)) { // DAR is in the registry
|
||||
found = true;
|
||||
rendList.removeElementAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
rendList.insertElementAt(dar, 0);
|
||||
PlugInManager.setPlugInList(rendList, plType);
|
||||
PlugInManager.commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable tt) {
|
||||
//Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
private void message(String mesg) {
|
||||
LOGGER.debug(mesg);
|
||||
}
|
||||
|
||||
private void createGUI() {
|
||||
TextArea textBox = new TextArea(5, 50);
|
||||
add("Center", textBox);
|
||||
textBox.setEditable(false);
|
||||
addNotify();
|
||||
pack();
|
||||
|
||||
int scrWidth = (int) Toolkit.getDefaultToolkit().getScreenSize()
|
||||
.getWidth();
|
||||
int scrHeight = (int) Toolkit.getDefaultToolkit().getScreenSize()
|
||||
.getHeight();
|
||||
|
||||
setLocation((scrWidth - getWidth()) / 2, (scrHeight - getHeight()) / 2);
|
||||
|
||||
setVisible(visible);
|
||||
|
||||
}
|
||||
|
||||
public static void start(boolean visible) {
|
||||
new JMFInit(null, visible);
|
||||
}
|
||||
}
|
||||
package org.jivesoftware.smackx.jingle.mediaimpl;
|
||||
|
||||
import java.awt.Frame;
|
||||
import java.awt.TextArea;
|
||||
import java.awt.Toolkit;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.media.Format;
|
||||
import javax.media.PlugInManager;
|
||||
import javax.media.Renderer;
|
||||
import javax.media.format.AudioFormat;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.SmackLogger;
|
||||
|
||||
import com.sun.media.ExclusiveUse;
|
||||
import com.sun.media.util.Registry;
|
||||
|
||||
public class JMFInit extends Frame implements Runnable {
|
||||
|
||||
private static final long serialVersionUID = 6476412003260641680L;
|
||||
|
||||
private static final SmackLogger LOGGER = SmackLogger.getLogger(JMFInit.class);
|
||||
|
||||
private String tempDir = "/tmp";
|
||||
|
||||
private boolean done = false;
|
||||
|
||||
private String userHome;
|
||||
|
||||
private boolean visible = false;
|
||||
|
||||
public JMFInit(String[] args, boolean visible) {
|
||||
super("Initializing JMF...");
|
||||
|
||||
this.visible = visible;
|
||||
|
||||
Registry.set("secure.allowCaptureFromApplets", true);
|
||||
Registry.set("secure.allowSaveFileFromApplets", true);
|
||||
|
||||
updateTemp(args);
|
||||
|
||||
try {
|
||||
Registry.commit();
|
||||
}
|
||||
catch (Exception e) {
|
||||
|
||||
message("Failed to commit to JMFRegistry!");
|
||||
}
|
||||
|
||||
Thread detectThread = new Thread(this);
|
||||
detectThread.run();
|
||||
|
||||
/*
|
||||
* int slept = 0; while (!done && slept < 60 * 1000 * 2) { try {
|
||||
* Thread.currentThread().sleep(500); } catch (InterruptedException ie) { }
|
||||
* slept += 500; }
|
||||
*
|
||||
* if (!done) { console.error("Detection is taking too long!
|
||||
* Aborting!"); message("Detection is taking too long! Aborting!"); }
|
||||
*
|
||||
* try { Thread.currentThread().sleep(2000); } catch
|
||||
* (InterruptedException ie) { }
|
||||
*/
|
||||
}
|
||||
|
||||
public void run() {
|
||||
detectDirectAudio();
|
||||
detectS8DirectAudio();
|
||||
detectCaptureDevices();
|
||||
done = true;
|
||||
}
|
||||
|
||||
private void updateTemp(String[] args) {
|
||||
if (args != null && args.length > 0) {
|
||||
tempDir = args[0];
|
||||
|
||||
message("Setting cache directory to " + tempDir);
|
||||
Registry r = new Registry();
|
||||
try {
|
||||
r.set("secure.cacheDir", tempDir);
|
||||
r.commit();
|
||||
|
||||
message("Updated registry");
|
||||
}
|
||||
catch (Exception e) {
|
||||
message("Couldn't update registry!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void detectCaptureDevices() {
|
||||
// check if JavaSound capture is available
|
||||
message("Looking for Audio capturer");
|
||||
Class<?> dsauto;
|
||||
try {
|
||||
dsauto = Class.forName("DirectSoundAuto");
|
||||
dsauto.newInstance();
|
||||
message("Finished detecting DirectSound capturer");
|
||||
}
|
||||
catch (ThreadDeath td) {
|
||||
throw td;
|
||||
}
|
||||
catch (Throwable t) {
|
||||
//Do nothing
|
||||
}
|
||||
|
||||
Class<?> jsauto;
|
||||
try {
|
||||
jsauto = Class.forName("JavaSoundAuto");
|
||||
jsauto.newInstance();
|
||||
message("Finished detecting javasound capturer");
|
||||
}
|
||||
catch (ThreadDeath td) {
|
||||
throw td;
|
||||
}
|
||||
catch (Throwable t) {
|
||||
message("JavaSound capturer detection failed!");
|
||||
}
|
||||
|
||||
/*
|
||||
// Check if VFWAuto or SunVideoAuto is available
|
||||
message("Looking for video capture devices");
|
||||
Class auto = null;
|
||||
Class autoPlus = null;
|
||||
try {
|
||||
auto = Class.forName("VFWAuto");
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
if (auto == null) {
|
||||
try {
|
||||
auto = Class.forName("SunVideoAuto");
|
||||
}
|
||||
catch (Exception ee) {
|
||||
|
||||
}
|
||||
try {
|
||||
autoPlus = Class.forName("SunVideoPlusAuto");
|
||||
}
|
||||
catch (Exception ee) {
|
||||
|
||||
}
|
||||
}
|
||||
if (auto == null) {
|
||||
try {
|
||||
auto = Class.forName("V4LAuto");
|
||||
}
|
||||
catch (Exception ee) {
|
||||
|
||||
}
|
||||
}
|
||||
try {
|
||||
Object instance = auto.newInstance();
|
||||
if (autoPlus != null) {
|
||||
Object instancePlus = autoPlus.newInstance();
|
||||
}
|
||||
|
||||
message("Finished detecting video capture devices");
|
||||
}
|
||||
catch (ThreadDeath td) {
|
||||
throw td;
|
||||
}
|
||||
catch (Throwable t) {
|
||||
|
||||
message("Capture device detection failed!");
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
private void detectDirectAudio() {
|
||||
Class<?> cls;
|
||||
int plType = PlugInManager.RENDERER;
|
||||
String dar = "com.sun.media.renderer.audio.DirectAudioRenderer";
|
||||
try {
|
||||
// Check if this is the Windows Performance Pack - hack
|
||||
cls = Class.forName("VFWAuto");
|
||||
// Check if DS capture is supported, otherwise fail DS renderer
|
||||
// since NT doesn't have capture
|
||||
cls = Class.forName("com.sun.media.protocol.dsound.DSound");
|
||||
// Find the renderer class and instantiate it.
|
||||
cls = Class.forName(dar);
|
||||
|
||||
Renderer rend = (Renderer) cls.newInstance();
|
||||
try {
|
||||
// Set the format and open the device
|
||||
AudioFormat af = new AudioFormat(AudioFormat.LINEAR, 44100, 16,
|
||||
2);
|
||||
rend.setInputFormat(af);
|
||||
rend.open();
|
||||
Format[] inputFormats = rend.getSupportedInputFormats();
|
||||
// Register the device
|
||||
PlugInManager.addPlugIn(dar, inputFormats, new Format[0],
|
||||
plType);
|
||||
// Move it to the top of the list
|
||||
Vector<String> rendList = PlugInManager.getPlugInList(null, null,
|
||||
plType);
|
||||
int listSize = rendList.size();
|
||||
if (rendList.elementAt(listSize - 1).equals(dar)) {
|
||||
rendList.removeElementAt(listSize - 1);
|
||||
rendList.insertElementAt(dar, 0);
|
||||
PlugInManager.setPlugInList(rendList, plType);
|
||||
PlugInManager.commit();
|
||||
// Log.debug("registered");
|
||||
}
|
||||
rend.close();
|
||||
}
|
||||
catch (Throwable t) {
|
||||
// Log.debug("Error " + t);
|
||||
}
|
||||
}
|
||||
catch (Throwable tt) {
|
||||
//Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
private void detectS8DirectAudio() {
|
||||
Class<?> cls;
|
||||
int plType = PlugInManager.RENDERER;
|
||||
String dar = "com.sun.media.renderer.audio.DirectAudioRenderer";
|
||||
try {
|
||||
// Check if this is the solaris Performance Pack - hack
|
||||
cls = Class.forName("SunVideoAuto");
|
||||
|
||||
// Find the renderer class and instantiate it.
|
||||
cls = Class.forName(dar);
|
||||
|
||||
Renderer rend = (Renderer) cls.newInstance();
|
||||
|
||||
if (rend instanceof ExclusiveUse
|
||||
&& !((ExclusiveUse) rend).isExclusive()) {
|
||||
// sol8+, DAR supports mixing
|
||||
Vector<String> rendList = PlugInManager.getPlugInList(null, null,
|
||||
plType);
|
||||
int listSize = rendList.size();
|
||||
boolean found = false;
|
||||
String rname = null;
|
||||
|
||||
for (int i = 0; i < listSize; i++) {
|
||||
rname = (String) (rendList.elementAt(i));
|
||||
if (rname.equals(dar)) { // DAR is in the registry
|
||||
found = true;
|
||||
rendList.removeElementAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
rendList.insertElementAt(dar, 0);
|
||||
PlugInManager.setPlugInList(rendList, plType);
|
||||
PlugInManager.commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable tt) {
|
||||
//Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
private void message(String mesg) {
|
||||
LOGGER.debug(mesg);
|
||||
}
|
||||
|
||||
private void createGUI() {
|
||||
TextArea textBox = new TextArea(5, 50);
|
||||
add("Center", textBox);
|
||||
textBox.setEditable(false);
|
||||
addNotify();
|
||||
pack();
|
||||
|
||||
int scrWidth = (int) Toolkit.getDefaultToolkit().getScreenSize()
|
||||
.getWidth();
|
||||
int scrHeight = (int) Toolkit.getDefaultToolkit().getScreenSize()
|
||||
.getHeight();
|
||||
|
||||
setLocation((scrWidth - getWidth()) / 2, (scrHeight - getHeight()) / 2);
|
||||
|
||||
setVisible(visible);
|
||||
|
||||
}
|
||||
|
||||
public static void start(boolean visible) {
|
||||
new JMFInit(null, visible);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,176 +1,176 @@
|
|||
/**
|
||||
* <p/>
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
* <p/>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.mediaimpl.demo;
|
||||
|
||||
import org.jivesoftware.smack.Connection;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smackx.jingle.JingleManager;
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
import org.jivesoftware.smackx.jingle.JingleSessionRequest;
|
||||
import org.jivesoftware.smackx.jingle.listeners.JingleSessionRequestListener;
|
||||
import org.jivesoftware.smackx.jingle.media.JingleMediaManager;
|
||||
import org.jivesoftware.smackx.jingle.mediaimpl.jspeex.SpeexMediaManager;
|
||||
import org.jivesoftware.smackx.jingle.mediaimpl.sshare.ScreenShareMediaManager;
|
||||
import org.jivesoftware.smackx.jingle.nat.ICETransportManager;
|
||||
import org.jivesoftware.smackx.jingle.nat.JingleTransportManager;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Jingle Demo Application. It register in a XMPP Server and let users place calls using a full JID and auto-receive calls.
|
||||
* Parameters: Server User Pass.
|
||||
*/
|
||||
public class Demo extends JFrame {
|
||||
|
||||
private static final long serialVersionUID = -6584021277434403855L;
|
||||
private JingleTransportManager transportManager = null;
|
||||
private Connection xmppConnection = null;
|
||||
|
||||
private String server = null;
|
||||
private String user = null;
|
||||
private String pass = null;
|
||||
|
||||
private JingleManager jm = null;
|
||||
private JingleSession incoming = null;
|
||||
private JingleSession outgoing = null;
|
||||
|
||||
private JTextField jid;
|
||||
|
||||
public Demo(String server, String user, String pass) {
|
||||
|
||||
this.server = server;
|
||||
this.user = user;
|
||||
this.pass = pass;
|
||||
|
||||
if (user.equals("jeffw")) {
|
||||
jid = new JTextField("eowyn" + "@" + server + "/Smack");
|
||||
} else {
|
||||
jid = new JTextField("jeffw" + "@" + server + "/Smack");
|
||||
}
|
||||
|
||||
xmppConnection = new XMPPConnection(server);
|
||||
try {
|
||||
xmppConnection.connect();
|
||||
xmppConnection.login(user, pass);
|
||||
initialize();
|
||||
}
|
||||
catch (XMPPException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void initialize() {
|
||||
ICETransportManager icetm0 = new ICETransportManager(xmppConnection, "10.47.47.53", 3478);
|
||||
List<JingleMediaManager> mediaManagers = new ArrayList<JingleMediaManager>();
|
||||
//mediaManagers.add(new JmfMediaManager(icetm0));
|
||||
mediaManagers.add(new SpeexMediaManager(icetm0));
|
||||
mediaManagers.add(new ScreenShareMediaManager(icetm0));
|
||||
jm = new JingleManager(xmppConnection, mediaManagers);
|
||||
jm.addCreationListener(icetm0);
|
||||
|
||||
jm.addJingleSessionRequestListener(new JingleSessionRequestListener() {
|
||||
public void sessionRequested(JingleSessionRequest request) {
|
||||
|
||||
// if (incoming != null)
|
||||
// return;
|
||||
|
||||
try {
|
||||
// Accept the call
|
||||
incoming = request.accept();
|
||||
|
||||
// Start the call
|
||||
incoming.startIncoming();
|
||||
}
|
||||
catch (XMPPException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
createGUI();
|
||||
}
|
||||
|
||||
public void createGUI() {
|
||||
|
||||
JPanel jPanel = new JPanel();
|
||||
|
||||
jPanel.add(jid);
|
||||
|
||||
jPanel.add(new JButton(new AbstractAction("Call") {
|
||||
private static final long serialVersionUID = 4308448034795312815L;
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (outgoing != null) return;
|
||||
try {
|
||||
outgoing = jm.createOutgoingJingleSession(jid.getText());
|
||||
outgoing.startOutgoing();
|
||||
}
|
||||
catch (XMPPException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
jPanel.add(new JButton(new AbstractAction("Hangup") {
|
||||
private static final long serialVersionUID = -4508007389146723587L;
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (outgoing != null)
|
||||
try {
|
||||
outgoing.terminate();
|
||||
}
|
||||
catch (XMPPException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
finally {
|
||||
outgoing = null;
|
||||
}
|
||||
if (incoming != null)
|
||||
try {
|
||||
incoming.terminate();
|
||||
}
|
||||
catch (XMPPException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
finally {
|
||||
incoming = null;
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
this.add(jPanel);
|
||||
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
|
||||
Demo demo = null;
|
||||
|
||||
if (args.length > 2) {
|
||||
demo = new Demo(args[0], args[1], args[2]);
|
||||
demo.pack();
|
||||
demo.setVisible(true);
|
||||
demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* <p/>
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
* <p/>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.mediaimpl.demo;
|
||||
|
||||
import org.jivesoftware.smack.Connection;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smackx.jingle.JingleManager;
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
import org.jivesoftware.smackx.jingle.JingleSessionRequest;
|
||||
import org.jivesoftware.smackx.jingle.listeners.JingleSessionRequestListener;
|
||||
import org.jivesoftware.smackx.jingle.media.JingleMediaManager;
|
||||
import org.jivesoftware.smackx.jingle.mediaimpl.jspeex.SpeexMediaManager;
|
||||
import org.jivesoftware.smackx.jingle.mediaimpl.sshare.ScreenShareMediaManager;
|
||||
import org.jivesoftware.smackx.jingle.nat.ICETransportManager;
|
||||
import org.jivesoftware.smackx.jingle.nat.JingleTransportManager;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Jingle Demo Application. It register in a XMPP Server and let users place calls using a full JID and auto-receive calls.
|
||||
* Parameters: Server User Pass.
|
||||
*/
|
||||
public class Demo extends JFrame {
|
||||
|
||||
private static final long serialVersionUID = -6584021277434403855L;
|
||||
private JingleTransportManager transportManager = null;
|
||||
private Connection xmppConnection = null;
|
||||
|
||||
private String server = null;
|
||||
private String user = null;
|
||||
private String pass = null;
|
||||
|
||||
private JingleManager jm = null;
|
||||
private JingleSession incoming = null;
|
||||
private JingleSession outgoing = null;
|
||||
|
||||
private JTextField jid;
|
||||
|
||||
public Demo(String server, String user, String pass) {
|
||||
|
||||
this.server = server;
|
||||
this.user = user;
|
||||
this.pass = pass;
|
||||
|
||||
if (user.equals("jeffw")) {
|
||||
jid = new JTextField("eowyn" + "@" + server + "/Smack");
|
||||
} else {
|
||||
jid = new JTextField("jeffw" + "@" + server + "/Smack");
|
||||
}
|
||||
|
||||
xmppConnection = new XMPPConnection(server);
|
||||
try {
|
||||
xmppConnection.connect();
|
||||
xmppConnection.login(user, pass);
|
||||
initialize();
|
||||
}
|
||||
catch (XMPPException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void initialize() {
|
||||
ICETransportManager icetm0 = new ICETransportManager(xmppConnection, "10.47.47.53", 3478);
|
||||
List<JingleMediaManager> mediaManagers = new ArrayList<JingleMediaManager>();
|
||||
//mediaManagers.add(new JmfMediaManager(icetm0));
|
||||
mediaManagers.add(new SpeexMediaManager(icetm0));
|
||||
mediaManagers.add(new ScreenShareMediaManager(icetm0));
|
||||
jm = new JingleManager(xmppConnection, mediaManagers);
|
||||
jm.addCreationListener(icetm0);
|
||||
|
||||
jm.addJingleSessionRequestListener(new JingleSessionRequestListener() {
|
||||
public void sessionRequested(JingleSessionRequest request) {
|
||||
|
||||
// if (incoming != null)
|
||||
// return;
|
||||
|
||||
try {
|
||||
// Accept the call
|
||||
incoming = request.accept();
|
||||
|
||||
// Start the call
|
||||
incoming.startIncoming();
|
||||
}
|
||||
catch (XMPPException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
createGUI();
|
||||
}
|
||||
|
||||
public void createGUI() {
|
||||
|
||||
JPanel jPanel = new JPanel();
|
||||
|
||||
jPanel.add(jid);
|
||||
|
||||
jPanel.add(new JButton(new AbstractAction("Call") {
|
||||
private static final long serialVersionUID = 4308448034795312815L;
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (outgoing != null) return;
|
||||
try {
|
||||
outgoing = jm.createOutgoingJingleSession(jid.getText());
|
||||
outgoing.startOutgoing();
|
||||
}
|
||||
catch (XMPPException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
jPanel.add(new JButton(new AbstractAction("Hangup") {
|
||||
private static final long serialVersionUID = -4508007389146723587L;
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (outgoing != null)
|
||||
try {
|
||||
outgoing.terminate();
|
||||
}
|
||||
catch (XMPPException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
finally {
|
||||
outgoing = null;
|
||||
}
|
||||
if (incoming != null)
|
||||
try {
|
||||
incoming.terminate();
|
||||
}
|
||||
catch (XMPPException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
finally {
|
||||
incoming = null;
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
this.add(jPanel);
|
||||
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
|
||||
Demo demo = null;
|
||||
|
||||
if (args.length > 2) {
|
||||
demo = new Demo(args[0], args[1], args[2]);
|
||||
demo.pack();
|
||||
demo.setVisible(true);
|
||||
demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,52 +1,52 @@
|
|||
/**
|
||||
* <p/>
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
* <p/>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.mediaimpl.jmf;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.media.PayloadType;
|
||||
|
||||
import javax.media.format.AudioFormat;
|
||||
|
||||
/**
|
||||
* Audio Format Utils.
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public class AudioFormatUtils {
|
||||
|
||||
/**
|
||||
* Return a JMF AudioFormat for a given Jingle Payload type.
|
||||
* Return null if the payload is not supported by this jmf API.
|
||||
*
|
||||
* @param payloadtype payloadtype
|
||||
* @return correspondent audioType
|
||||
*/
|
||||
public static AudioFormat getAudioFormat(PayloadType payloadtype) {
|
||||
|
||||
switch (payloadtype.getId()) {
|
||||
case 0:
|
||||
return new AudioFormat(AudioFormat.ULAW_RTP);
|
||||
case 3:
|
||||
return new AudioFormat(AudioFormat.GSM_RTP);
|
||||
case 4:
|
||||
return new AudioFormat(AudioFormat.G723_RTP);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* <p/>
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
* <p/>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.mediaimpl.jmf;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.media.PayloadType;
|
||||
|
||||
import javax.media.format.AudioFormat;
|
||||
|
||||
/**
|
||||
* Audio Format Utils.
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public class AudioFormatUtils {
|
||||
|
||||
/**
|
||||
* Return a JMF AudioFormat for a given Jingle Payload type.
|
||||
* Return null if the payload is not supported by this jmf API.
|
||||
*
|
||||
* @param payloadtype payloadtype
|
||||
* @return correspondent audioType
|
||||
*/
|
||||
public static AudioFormat getAudioFormat(PayloadType payloadtype) {
|
||||
|
||||
switch (payloadtype.getId()) {
|
||||
case 0:
|
||||
return new AudioFormat(AudioFormat.ULAW_RTP);
|
||||
case 3:
|
||||
return new AudioFormat(AudioFormat.GSM_RTP);
|
||||
case 4:
|
||||
return new AudioFormat(AudioFormat.G723_RTP);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,162 +1,162 @@
|
|||
/**
|
||||
* <p/>
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
* <p/>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jivesoftware.smackx.jingle.mediaimpl.jmf;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
|
||||
import javax.media.MediaLocator;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
import org.jivesoftware.smackx.jingle.SmackLogger;
|
||||
import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
|
||||
import org.jivesoftware.smackx.jingle.media.PayloadType;
|
||||
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
|
||||
|
||||
/**
|
||||
* This Class implements a complete JingleMediaSession.
|
||||
* It sould be used to transmit and receive audio captured from the Mic.
|
||||
* This Class should be automaticly controlled by JingleSession.
|
||||
* But you could also use in any VOIP application.
|
||||
* For better NAT Traversal support this implementation don't support only receive or only transmit.
|
||||
* To receive you MUST transmit. So the only implemented and functionally methods are startTransmit() and stopTransmit()
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public class AudioMediaSession extends JingleMediaSession {
|
||||
|
||||
private static final SmackLogger LOGGER = SmackLogger.getLogger(AudioMediaSession.class);
|
||||
|
||||
private AudioChannel audioChannel;
|
||||
|
||||
/**
|
||||
* Creates a org.jivesoftware.jingleaudio.jmf.AudioMediaSession with defined payload type, remote and local candidates
|
||||
*
|
||||
* @param payloadType Payload of the jmf
|
||||
* @param remote the remote information. The candidate that the jmf will be sent to.
|
||||
* @param local the local information. The candidate that will receive the jmf
|
||||
* @param locator media locator
|
||||
*/
|
||||
public AudioMediaSession(final PayloadType payloadType, final TransportCandidate remote,
|
||||
final TransportCandidate local, String locator, JingleSession jingleSession) {
|
||||
super(payloadType, remote, local, locator==null?"dsound://":locator,jingleSession);
|
||||
initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the Audio Channel to make it able to send and receive audio
|
||||
*/
|
||||
public void initialize() {
|
||||
|
||||
String ip;
|
||||
String localIp;
|
||||
int localPort;
|
||||
int remotePort;
|
||||
|
||||
if (this.getLocal().getSymmetric() != null) {
|
||||
ip = this.getLocal().getIp();
|
||||
localIp = this.getLocal().getLocalIp();
|
||||
localPort = getFreePort();
|
||||
remotePort = this.getLocal().getSymmetric().getPort();
|
||||
|
||||
LOGGER.debug(this.getLocal().getConnection() + " " + ip + ": " + localPort + "->" + remotePort);
|
||||
|
||||
}
|
||||
else {
|
||||
ip = this.getRemote().getIp();
|
||||
localIp = this.getLocal().getLocalIp();
|
||||
localPort = this.getLocal().getPort();
|
||||
remotePort = this.getRemote().getPort();
|
||||
}
|
||||
|
||||
audioChannel = new AudioChannel(new MediaLocator(this.getMediaLocator()), localIp, ip, localPort, remotePort, AudioFormatUtils.getAudioFormat(this.getPayloadType()),this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts transmission and for NAT Traversal reasons start receiving also.
|
||||
*/
|
||||
public void startTrasmit() {
|
||||
audioChannel.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set transmit activity. If the active is true, the instance should trasmit.
|
||||
* If it is set to false, the instance should pause transmit.
|
||||
*
|
||||
* @param active active state
|
||||
*/
|
||||
public void setTrasmit(boolean active) {
|
||||
audioChannel.setTrasmit(active);
|
||||
}
|
||||
|
||||
/**
|
||||
* For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf
|
||||
*/
|
||||
public void startReceive() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops transmission and for NAT Traversal reasons stop receiving also.
|
||||
*/
|
||||
public void stopTrasmit() {
|
||||
if (audioChannel != null)
|
||||
audioChannel.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf
|
||||
*/
|
||||
public void stopReceive() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a free port we can use.
|
||||
*
|
||||
* @return A free port number.
|
||||
*/
|
||||
protected int getFreePort() {
|
||||
ServerSocket ss;
|
||||
int freePort = 0;
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
freePort = (int) (10000 + Math.round(Math.random() * 10000));
|
||||
freePort = freePort % 2 == 0 ? freePort : freePort + 1;
|
||||
try {
|
||||
ss = new ServerSocket(freePort);
|
||||
freePort = ss.getLocalPort();
|
||||
ss.close();
|
||||
return freePort;
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
try {
|
||||
ss = new ServerSocket(0);
|
||||
freePort = ss.getLocalPort();
|
||||
ss.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return freePort;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* <p/>
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
* <p/>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jivesoftware.smackx.jingle.mediaimpl.jmf;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
|
||||
import javax.media.MediaLocator;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
import org.jivesoftware.smackx.jingle.SmackLogger;
|
||||
import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
|
||||
import org.jivesoftware.smackx.jingle.media.PayloadType;
|
||||
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
|
||||
|
||||
/**
|
||||
* This Class implements a complete JingleMediaSession.
|
||||
* It sould be used to transmit and receive audio captured from the Mic.
|
||||
* This Class should be automaticly controlled by JingleSession.
|
||||
* But you could also use in any VOIP application.
|
||||
* For better NAT Traversal support this implementation don't support only receive or only transmit.
|
||||
* To receive you MUST transmit. So the only implemented and functionally methods are startTransmit() and stopTransmit()
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public class AudioMediaSession extends JingleMediaSession {
|
||||
|
||||
private static final SmackLogger LOGGER = SmackLogger.getLogger(AudioMediaSession.class);
|
||||
|
||||
private AudioChannel audioChannel;
|
||||
|
||||
/**
|
||||
* Creates a org.jivesoftware.jingleaudio.jmf.AudioMediaSession with defined payload type, remote and local candidates
|
||||
*
|
||||
* @param payloadType Payload of the jmf
|
||||
* @param remote the remote information. The candidate that the jmf will be sent to.
|
||||
* @param local the local information. The candidate that will receive the jmf
|
||||
* @param locator media locator
|
||||
*/
|
||||
public AudioMediaSession(final PayloadType payloadType, final TransportCandidate remote,
|
||||
final TransportCandidate local, String locator, JingleSession jingleSession) {
|
||||
super(payloadType, remote, local, locator==null?"dsound://":locator,jingleSession);
|
||||
initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the Audio Channel to make it able to send and receive audio
|
||||
*/
|
||||
public void initialize() {
|
||||
|
||||
String ip;
|
||||
String localIp;
|
||||
int localPort;
|
||||
int remotePort;
|
||||
|
||||
if (this.getLocal().getSymmetric() != null) {
|
||||
ip = this.getLocal().getIp();
|
||||
localIp = this.getLocal().getLocalIp();
|
||||
localPort = getFreePort();
|
||||
remotePort = this.getLocal().getSymmetric().getPort();
|
||||
|
||||
LOGGER.debug(this.getLocal().getConnection() + " " + ip + ": " + localPort + "->" + remotePort);
|
||||
|
||||
}
|
||||
else {
|
||||
ip = this.getRemote().getIp();
|
||||
localIp = this.getLocal().getLocalIp();
|
||||
localPort = this.getLocal().getPort();
|
||||
remotePort = this.getRemote().getPort();
|
||||
}
|
||||
|
||||
audioChannel = new AudioChannel(new MediaLocator(this.getMediaLocator()), localIp, ip, localPort, remotePort, AudioFormatUtils.getAudioFormat(this.getPayloadType()),this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts transmission and for NAT Traversal reasons start receiving also.
|
||||
*/
|
||||
public void startTrasmit() {
|
||||
audioChannel.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set transmit activity. If the active is true, the instance should trasmit.
|
||||
* If it is set to false, the instance should pause transmit.
|
||||
*
|
||||
* @param active active state
|
||||
*/
|
||||
public void setTrasmit(boolean active) {
|
||||
audioChannel.setTrasmit(active);
|
||||
}
|
||||
|
||||
/**
|
||||
* For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf
|
||||
*/
|
||||
public void startReceive() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops transmission and for NAT Traversal reasons stop receiving also.
|
||||
*/
|
||||
public void stopTrasmit() {
|
||||
if (audioChannel != null)
|
||||
audioChannel.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf
|
||||
*/
|
||||
public void stopReceive() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a free port we can use.
|
||||
*
|
||||
* @return A free port number.
|
||||
*/
|
||||
protected int getFreePort() {
|
||||
ServerSocket ss;
|
||||
int freePort = 0;
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
freePort = (int) (10000 + Math.round(Math.random() * 10000));
|
||||
freePort = freePort % 2 == 0 ? freePort : freePort + 1;
|
||||
try {
|
||||
ss = new ServerSocket(freePort);
|
||||
freePort = ss.getLocalPort();
|
||||
ss.close();
|
||||
return freePort;
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
try {
|
||||
ss = new ServerSocket(0);
|
||||
freePort = ss.getLocalPort();
|
||||
ss.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return freePort;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,168 +1,168 @@
|
|||
/**
|
||||
* <p/>
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
* <p/>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jivesoftware.smackx.jingle.mediaimpl.jmf;
|
||||
|
||||
import javax.media.ControllerErrorEvent;
|
||||
import javax.media.ControllerEvent;
|
||||
import javax.media.ControllerListener;
|
||||
import javax.media.Player;
|
||||
import javax.media.RealizeCompleteEvent;
|
||||
import javax.media.protocol.DataSource;
|
||||
import javax.media.rtp.Participant;
|
||||
import javax.media.rtp.RTPControl;
|
||||
import javax.media.rtp.ReceiveStream;
|
||||
import javax.media.rtp.ReceiveStreamListener;
|
||||
import javax.media.rtp.SessionListener;
|
||||
import javax.media.rtp.event.ByeEvent;
|
||||
import javax.media.rtp.event.NewParticipantEvent;
|
||||
import javax.media.rtp.event.NewReceiveStreamEvent;
|
||||
import javax.media.rtp.event.ReceiveStreamEvent;
|
||||
import javax.media.rtp.event.RemotePayloadChangeEvent;
|
||||
import javax.media.rtp.event.SessionEvent;
|
||||
import javax.media.rtp.event.StreamMappedEvent;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.SmackLogger;
|
||||
import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
|
||||
|
||||
/**
|
||||
* This class implements receive methods and listeners to be used in AudioChannel
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public class AudioReceiver implements ReceiveStreamListener, SessionListener,
|
||||
ControllerListener {
|
||||
|
||||
private static final SmackLogger LOGGER = SmackLogger.getLogger(AudioReceiver.class);
|
||||
|
||||
boolean dataReceived = false;
|
||||
|
||||
Object dataSync;
|
||||
JingleMediaSession jingleMediaSession;
|
||||
|
||||
public AudioReceiver(final Object dataSync, final JingleMediaSession jingleMediaSession) {
|
||||
this.dataSync = dataSync;
|
||||
this.jingleMediaSession = jingleMediaSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* JingleSessionListener.
|
||||
*/
|
||||
public synchronized void update(SessionEvent evt) {
|
||||
if (evt instanceof NewParticipantEvent) {
|
||||
Participant p = ((NewParticipantEvent) evt).getParticipant();
|
||||
LOGGER.error(" - A new participant had just joined: " + p.getCNAME());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ReceiveStreamListener
|
||||
*/
|
||||
public synchronized void update(ReceiveStreamEvent evt) {
|
||||
|
||||
Participant participant = evt.getParticipant(); // could be null.
|
||||
ReceiveStream stream = evt.getReceiveStream(); // could be null.
|
||||
|
||||
if (evt instanceof RemotePayloadChangeEvent) {
|
||||
LOGGER.error(" - Received an RTP PayloadChangeEvent.");
|
||||
LOGGER.error("Sorry, cannot handle payload change.");
|
||||
|
||||
}
|
||||
else if (evt instanceof NewReceiveStreamEvent) {
|
||||
|
||||
try {
|
||||
stream = evt.getReceiveStream();
|
||||
DataSource ds = stream.getDataSource();
|
||||
|
||||
// Find out the formats.
|
||||
RTPControl ctl = (RTPControl) ds.getControl("javax.jmf.rtp.RTPControl");
|
||||
if (ctl != null) {
|
||||
LOGGER.error(" - Recevied new RTP stream: " + ctl.getFormat());
|
||||
}
|
||||
else
|
||||
LOGGER.error(" - Recevied new RTP stream");
|
||||
|
||||
if (participant == null)
|
||||
LOGGER.error(" The sender of this stream had yet to be identified.");
|
||||
else {
|
||||
LOGGER.error(" The stream comes from: " + participant.getCNAME());
|
||||
}
|
||||
|
||||
// create a player by passing datasource to the Media Manager
|
||||
Player p = javax.media.Manager.createPlayer(ds);
|
||||
if (p == null)
|
||||
return;
|
||||
|
||||
p.addControllerListener(this);
|
||||
p.realize();
|
||||
jingleMediaSession.mediaReceived(participant != null ? participant.getCNAME() : "");
|
||||
|
||||
// Notify intialize() that a new stream had arrived.
|
||||
synchronized (dataSync) {
|
||||
dataReceived = true;
|
||||
dataSync.notifyAll();
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOGGER.error("NewReceiveStreamEvent exception " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
else if (evt instanceof StreamMappedEvent) {
|
||||
|
||||
if (stream != null && stream.getDataSource() != null) {
|
||||
DataSource ds = stream.getDataSource();
|
||||
// Find out the formats.
|
||||
RTPControl ctl = (RTPControl) ds.getControl("javax.jmf.rtp.RTPControl");
|
||||
LOGGER.error(" - The previously unidentified stream ");
|
||||
if (ctl != null)
|
||||
LOGGER.error(" " + ctl.getFormat());
|
||||
LOGGER.error(" had now been identified as sent by: " + participant.getCNAME());
|
||||
}
|
||||
}
|
||||
else if (evt instanceof ByeEvent) {
|
||||
|
||||
LOGGER.error(" - Got \"bye\" from: " + participant.getCNAME());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* ControllerListener for the Players.
|
||||
*/
|
||||
public synchronized void controllerUpdate(ControllerEvent ce) {
|
||||
|
||||
Player p = (Player) ce.getSourceController();
|
||||
|
||||
if (p == null)
|
||||
return;
|
||||
|
||||
// Get this when the internal players are realized.
|
||||
if (ce instanceof RealizeCompleteEvent) {
|
||||
p.start();
|
||||
}
|
||||
|
||||
if (ce instanceof ControllerErrorEvent) {
|
||||
p.removeControllerListener(this);
|
||||
LOGGER.error("Receiver internal error: " + ce);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
/**
|
||||
* <p/>
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
* <p/>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jivesoftware.smackx.jingle.mediaimpl.jmf;
|
||||
|
||||
import javax.media.ControllerErrorEvent;
|
||||
import javax.media.ControllerEvent;
|
||||
import javax.media.ControllerListener;
|
||||
import javax.media.Player;
|
||||
import javax.media.RealizeCompleteEvent;
|
||||
import javax.media.protocol.DataSource;
|
||||
import javax.media.rtp.Participant;
|
||||
import javax.media.rtp.RTPControl;
|
||||
import javax.media.rtp.ReceiveStream;
|
||||
import javax.media.rtp.ReceiveStreamListener;
|
||||
import javax.media.rtp.SessionListener;
|
||||
import javax.media.rtp.event.ByeEvent;
|
||||
import javax.media.rtp.event.NewParticipantEvent;
|
||||
import javax.media.rtp.event.NewReceiveStreamEvent;
|
||||
import javax.media.rtp.event.ReceiveStreamEvent;
|
||||
import javax.media.rtp.event.RemotePayloadChangeEvent;
|
||||
import javax.media.rtp.event.SessionEvent;
|
||||
import javax.media.rtp.event.StreamMappedEvent;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.SmackLogger;
|
||||
import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
|
||||
|
||||
/**
|
||||
* This class implements receive methods and listeners to be used in AudioChannel
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public class AudioReceiver implements ReceiveStreamListener, SessionListener,
|
||||
ControllerListener {
|
||||
|
||||
private static final SmackLogger LOGGER = SmackLogger.getLogger(AudioReceiver.class);
|
||||
|
||||
boolean dataReceived = false;
|
||||
|
||||
Object dataSync;
|
||||
JingleMediaSession jingleMediaSession;
|
||||
|
||||
public AudioReceiver(final Object dataSync, final JingleMediaSession jingleMediaSession) {
|
||||
this.dataSync = dataSync;
|
||||
this.jingleMediaSession = jingleMediaSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* JingleSessionListener.
|
||||
*/
|
||||
public synchronized void update(SessionEvent evt) {
|
||||
if (evt instanceof NewParticipantEvent) {
|
||||
Participant p = ((NewParticipantEvent) evt).getParticipant();
|
||||
LOGGER.error(" - A new participant had just joined: " + p.getCNAME());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ReceiveStreamListener
|
||||
*/
|
||||
public synchronized void update(ReceiveStreamEvent evt) {
|
||||
|
||||
Participant participant = evt.getParticipant(); // could be null.
|
||||
ReceiveStream stream = evt.getReceiveStream(); // could be null.
|
||||
|
||||
if (evt instanceof RemotePayloadChangeEvent) {
|
||||
LOGGER.error(" - Received an RTP PayloadChangeEvent.");
|
||||
LOGGER.error("Sorry, cannot handle payload change.");
|
||||
|
||||
}
|
||||
else if (evt instanceof NewReceiveStreamEvent) {
|
||||
|
||||
try {
|
||||
stream = evt.getReceiveStream();
|
||||
DataSource ds = stream.getDataSource();
|
||||
|
||||
// Find out the formats.
|
||||
RTPControl ctl = (RTPControl) ds.getControl("javax.jmf.rtp.RTPControl");
|
||||
if (ctl != null) {
|
||||
LOGGER.error(" - Recevied new RTP stream: " + ctl.getFormat());
|
||||
}
|
||||
else
|
||||
LOGGER.error(" - Recevied new RTP stream");
|
||||
|
||||
if (participant == null)
|
||||
LOGGER.error(" The sender of this stream had yet to be identified.");
|
||||
else {
|
||||
LOGGER.error(" The stream comes from: " + participant.getCNAME());
|
||||
}
|
||||
|
||||
// create a player by passing datasource to the Media Manager
|
||||
Player p = javax.media.Manager.createPlayer(ds);
|
||||
if (p == null)
|
||||
return;
|
||||
|
||||
p.addControllerListener(this);
|
||||
p.realize();
|
||||
jingleMediaSession.mediaReceived(participant != null ? participant.getCNAME() : "");
|
||||
|
||||
// Notify intialize() that a new stream had arrived.
|
||||
synchronized (dataSync) {
|
||||
dataReceived = true;
|
||||
dataSync.notifyAll();
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOGGER.error("NewReceiveStreamEvent exception " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
else if (evt instanceof StreamMappedEvent) {
|
||||
|
||||
if (stream != null && stream.getDataSource() != null) {
|
||||
DataSource ds = stream.getDataSource();
|
||||
// Find out the formats.
|
||||
RTPControl ctl = (RTPControl) ds.getControl("javax.jmf.rtp.RTPControl");
|
||||
LOGGER.error(" - The previously unidentified stream ");
|
||||
if (ctl != null)
|
||||
LOGGER.error(" " + ctl.getFormat());
|
||||
LOGGER.error(" had now been identified as sent by: " + participant.getCNAME());
|
||||
}
|
||||
}
|
||||
else if (evt instanceof ByeEvent) {
|
||||
|
||||
LOGGER.error(" - Got \"bye\" from: " + participant.getCNAME());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* ControllerListener for the Players.
|
||||
*/
|
||||
public synchronized void controllerUpdate(ControllerEvent ce) {
|
||||
|
||||
Player p = (Player) ce.getSourceController();
|
||||
|
||||
if (p == null)
|
||||
return;
|
||||
|
||||
// Get this when the internal players are realized.
|
||||
if (ce instanceof RealizeCompleteEvent) {
|
||||
p.start();
|
||||
}
|
||||
|
||||
if (ce instanceof ControllerErrorEvent) {
|
||||
p.removeControllerListener(this);
|
||||
LOGGER.error("Receiver internal error: " + ce);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,167 +1,167 @@
|
|||
/**
|
||||
* <p/>
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
* <p/>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jivesoftware.smackx.jingle.mediaimpl.jmf;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
import org.jivesoftware.smackx.jingle.SmackLogger;
|
||||
import org.jivesoftware.smackx.jingle.media.JingleMediaManager;
|
||||
import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
|
||||
import org.jivesoftware.smackx.jingle.media.PayloadType;
|
||||
import org.jivesoftware.smackx.jingle.mediaimpl.JMFInit;
|
||||
import org.jivesoftware.smackx.jingle.nat.JingleTransportManager;
|
||||
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
|
||||
|
||||
/**
|
||||
* Implements a jingleMediaManager using JMF based API.
|
||||
* It supports GSM and G723 codecs.
|
||||
* <i>This API only currently works on windows and Mac.</i>
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public class JmfMediaManager extends JingleMediaManager {
|
||||
|
||||
private static final SmackLogger LOGGER = SmackLogger.getLogger(JmfMediaManager.class);
|
||||
|
||||
public static final String MEDIA_NAME = "JMF";
|
||||
|
||||
|
||||
private List<PayloadType> payloads = new ArrayList<PayloadType>();
|
||||
private String mediaLocator = null;
|
||||
|
||||
/**
|
||||
* Creates a Media Manager instance
|
||||
*/
|
||||
public JmfMediaManager(JingleTransportManager transportManager) {
|
||||
super(transportManager);
|
||||
setupPayloads();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Media Manager instance
|
||||
*
|
||||
* @param mediaLocator Media Locator
|
||||
*/
|
||||
public JmfMediaManager(String mediaLocator, JingleTransportManager transportManager) {
|
||||
super(transportManager);
|
||||
this.mediaLocator = mediaLocator;
|
||||
setupPayloads();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new jingleMediaSession
|
||||
*
|
||||
* @param payloadType payloadType
|
||||
* @param remote remote Candidate
|
||||
* @param local local Candidate
|
||||
* @return JingleMediaSession
|
||||
*/
|
||||
public JingleMediaSession createMediaSession(final PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) {
|
||||
return new AudioMediaSession(payloadType, remote, local, mediaLocator, jingleSession);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup API supported Payloads
|
||||
*/
|
||||
private void setupPayloads() {
|
||||
payloads.add(new PayloadType.Audio(3, "gsm"));
|
||||
payloads.add(new PayloadType.Audio(4, "g723"));
|
||||
payloads.add(new PayloadType.Audio(0, "PCMU", 16000));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all supported Payloads for this Manager
|
||||
*
|
||||
* @return The Payload List
|
||||
*/
|
||||
public List<PayloadType> getPayloads() {
|
||||
return payloads;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the media locator or null if not defined
|
||||
*
|
||||
* @return media locator
|
||||
*/
|
||||
public String getMediaLocator() {
|
||||
return mediaLocator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the media locator
|
||||
*
|
||||
* @param mediaLocator media locator or null to use default
|
||||
*/
|
||||
public void setMediaLocator(String mediaLocator) {
|
||||
this.mediaLocator = mediaLocator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs JMFInit the first time the application is started so that capture
|
||||
* devices are properly detected and initialized by JMF.
|
||||
*/
|
||||
public static void setupJMF() {
|
||||
// .jmf is the place where we store the jmf.properties file used
|
||||
// by JMF. if the directory does not exist or it does not contain
|
||||
// a jmf.properties file. or if the jmf.properties file has 0 length
|
||||
// then this is the first time we're running and should continue to
|
||||
// with JMFInit
|
||||
String homeDir = System.getProperty("user.home");
|
||||
File jmfDir = new File(homeDir, ".jmf");
|
||||
String classpath = System.getProperty("java.class.path");
|
||||
classpath += System.getProperty("path.separator")
|
||||
+ jmfDir.getAbsolutePath();
|
||||
System.setProperty("java.class.path", classpath);
|
||||
|
||||
if (!jmfDir.exists())
|
||||
jmfDir.mkdir();
|
||||
|
||||
File jmfProperties = new File(jmfDir, "jmf.properties");
|
||||
|
||||
if (!jmfProperties.exists()) {
|
||||
try {
|
||||
jmfProperties.createNewFile();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
LOGGER.debug("Failed to create jmf.properties");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// if we're running on linux checkout that libjmutil.so is where it
|
||||
// should be and put it there.
|
||||
runLinuxPreInstall();
|
||||
|
||||
//if (jmfProperties.length() == 0) {
|
||||
new JMFInit(null, false);
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
private static void runLinuxPreInstall() {
|
||||
// @TODO Implement Linux Pre-Install
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return MEDIA_NAME;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* <p/>
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
* <p/>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jivesoftware.smackx.jingle.mediaimpl.jmf;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
import org.jivesoftware.smackx.jingle.SmackLogger;
|
||||
import org.jivesoftware.smackx.jingle.media.JingleMediaManager;
|
||||
import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
|
||||
import org.jivesoftware.smackx.jingle.media.PayloadType;
|
||||
import org.jivesoftware.smackx.jingle.mediaimpl.JMFInit;
|
||||
import org.jivesoftware.smackx.jingle.nat.JingleTransportManager;
|
||||
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
|
||||
|
||||
/**
|
||||
* Implements a jingleMediaManager using JMF based API.
|
||||
* It supports GSM and G723 codecs.
|
||||
* <i>This API only currently works on windows and Mac.</i>
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public class JmfMediaManager extends JingleMediaManager {
|
||||
|
||||
private static final SmackLogger LOGGER = SmackLogger.getLogger(JmfMediaManager.class);
|
||||
|
||||
public static final String MEDIA_NAME = "JMF";
|
||||
|
||||
|
||||
private List<PayloadType> payloads = new ArrayList<PayloadType>();
|
||||
private String mediaLocator = null;
|
||||
|
||||
/**
|
||||
* Creates a Media Manager instance
|
||||
*/
|
||||
public JmfMediaManager(JingleTransportManager transportManager) {
|
||||
super(transportManager);
|
||||
setupPayloads();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Media Manager instance
|
||||
*
|
||||
* @param mediaLocator Media Locator
|
||||
*/
|
||||
public JmfMediaManager(String mediaLocator, JingleTransportManager transportManager) {
|
||||
super(transportManager);
|
||||
this.mediaLocator = mediaLocator;
|
||||
setupPayloads();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new jingleMediaSession
|
||||
*
|
||||
* @param payloadType payloadType
|
||||
* @param remote remote Candidate
|
||||
* @param local local Candidate
|
||||
* @return JingleMediaSession
|
||||
*/
|
||||
public JingleMediaSession createMediaSession(final PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) {
|
||||
return new AudioMediaSession(payloadType, remote, local, mediaLocator, jingleSession);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup API supported Payloads
|
||||
*/
|
||||
private void setupPayloads() {
|
||||
payloads.add(new PayloadType.Audio(3, "gsm"));
|
||||
payloads.add(new PayloadType.Audio(4, "g723"));
|
||||
payloads.add(new PayloadType.Audio(0, "PCMU", 16000));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all supported Payloads for this Manager
|
||||
*
|
||||
* @return The Payload List
|
||||
*/
|
||||
public List<PayloadType> getPayloads() {
|
||||
return payloads;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the media locator or null if not defined
|
||||
*
|
||||
* @return media locator
|
||||
*/
|
||||
public String getMediaLocator() {
|
||||
return mediaLocator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the media locator
|
||||
*
|
||||
* @param mediaLocator media locator or null to use default
|
||||
*/
|
||||
public void setMediaLocator(String mediaLocator) {
|
||||
this.mediaLocator = mediaLocator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs JMFInit the first time the application is started so that capture
|
||||
* devices are properly detected and initialized by JMF.
|
||||
*/
|
||||
public static void setupJMF() {
|
||||
// .jmf is the place where we store the jmf.properties file used
|
||||
// by JMF. if the directory does not exist or it does not contain
|
||||
// a jmf.properties file. or if the jmf.properties file has 0 length
|
||||
// then this is the first time we're running and should continue to
|
||||
// with JMFInit
|
||||
String homeDir = System.getProperty("user.home");
|
||||
File jmfDir = new File(homeDir, ".jmf");
|
||||
String classpath = System.getProperty("java.class.path");
|
||||
classpath += System.getProperty("path.separator")
|
||||
+ jmfDir.getAbsolutePath();
|
||||
System.setProperty("java.class.path", classpath);
|
||||
|
||||
if (!jmfDir.exists())
|
||||
jmfDir.mkdir();
|
||||
|
||||
File jmfProperties = new File(jmfDir, "jmf.properties");
|
||||
|
||||
if (!jmfProperties.exists()) {
|
||||
try {
|
||||
jmfProperties.createNewFile();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
LOGGER.debug("Failed to create jmf.properties");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// if we're running on linux checkout that libjmutil.so is where it
|
||||
// should be and put it there.
|
||||
runLinuxPreInstall();
|
||||
|
||||
//if (jmfProperties.length() == 0) {
|
||||
new JMFInit(null, false);
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
private static void runLinuxPreInstall() {
|
||||
// @TODO Implement Linux Pre-Install
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return MEDIA_NAME;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,242 +1,242 @@
|
|||
/**
|
||||
* <p/>
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
* <p/>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jivesoftware.smackx.jingle.mediaimpl.jspeex;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
import javax.media.NoProcessorException;
|
||||
import javax.media.format.UnsupportedFormatException;
|
||||
import javax.media.rtp.rtcp.SenderReport;
|
||||
import javax.media.rtp.rtcp.SourceDescription;
|
||||
|
||||
import mil.jfcom.cie.media.session.MediaSession;
|
||||
import mil.jfcom.cie.media.session.MediaSessionListener;
|
||||
import mil.jfcom.cie.media.session.StreamPlayer;
|
||||
import mil.jfcom.cie.media.srtp.packetizer.SpeexFormat;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
import org.jivesoftware.smackx.jingle.SmackLogger;
|
||||
import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
|
||||
import org.jivesoftware.smackx.jingle.media.PayloadType;
|
||||
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
|
||||
|
||||
/**
|
||||
* This Class implements a complete JingleMediaSession.
|
||||
* It sould be used to transmit and receive audio captured from the Mic.
|
||||
* This Class should be automaticly controlled by JingleSession.
|
||||
* But you could also use in any VOIP application.
|
||||
* For better NAT Traversal support this implementation don't support only receive or only transmit.
|
||||
* To receive you MUST transmit. So the only implemented and functionally methods are startTransmit() and stopTransmit()
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
|
||||
public class AudioMediaSession extends JingleMediaSession implements MediaSessionListener {
|
||||
|
||||
private static final SmackLogger LOGGER = SmackLogger.getLogger(AudioMediaSession.class);
|
||||
|
||||
private MediaSession mediaSession;
|
||||
|
||||
/**
|
||||
* Create a Session using Speex Codec
|
||||
*
|
||||
* @param localhost localHost
|
||||
* @param localPort localPort
|
||||
* @param remoteHost remoteHost
|
||||
* @param remotePort remotePort
|
||||
* @param eventHandler eventHandler
|
||||
* @param quality quality
|
||||
* @param secure secure
|
||||
* @param micOn micOn
|
||||
* @return MediaSession
|
||||
* @throws NoProcessorException
|
||||
* @throws UnsupportedFormatException
|
||||
* @throws IOException
|
||||
* @throws GeneralSecurityException
|
||||
*/
|
||||
public static MediaSession createSession(String localhost, int localPort, String remoteHost, int remotePort, MediaSessionListener eventHandler, int quality, boolean secure, boolean micOn) throws NoProcessorException, UnsupportedFormatException, IOException, GeneralSecurityException {
|
||||
|
||||
SpeexFormat.setFramesPerPacket(1);
|
||||
/**
|
||||
* The master key. Hardcoded for now.
|
||||
*/
|
||||
byte[] masterKey = new byte[]{(byte) 0xE1, (byte) 0xF9, 0x7A, 0x0D, 0x3E, 0x01, (byte) 0x8B, (byte) 0xE0, (byte) 0xD6, 0x4F, (byte) 0xA3, 0x2C, 0x06, (byte) 0xDE, 0x41, 0x39};
|
||||
|
||||
/**
|
||||
* The master salt. Hardcoded for now.
|
||||
*/
|
||||
byte[] masterSalt = new byte[]{0x0E, (byte) 0xC6, 0x75, (byte) 0xAD, 0x49, (byte) 0x8A, (byte) 0xFE, (byte) 0xEB, (byte) 0xB6, (byte) 0x96, 0x0B, 0x3A, (byte) 0xAB, (byte) 0xE6};
|
||||
|
||||
DatagramSocket[] localPorts = MediaSession.getLocalPorts(InetAddress.getByName(localhost), localPort);
|
||||
MediaSession session = MediaSession.createInstance(remoteHost, remotePort, localPorts, quality, secure, masterKey, masterSalt);
|
||||
session.setListener(eventHandler);
|
||||
|
||||
session.setSourceDescription(new SourceDescription[]{new SourceDescription(SourceDescription.SOURCE_DESC_NAME, "Superman", 1, false), new SourceDescription(SourceDescription.SOURCE_DESC_EMAIL, "cdcie.tester@je.jfcom.mil", 1, false), new SourceDescription(SourceDescription.SOURCE_DESC_LOC, InetAddress.getByName(localhost) + " Port " + session.getLocalDataPort(), 1, false), new SourceDescription(SourceDescription.SOURCE_DESC_TOOL, "JFCOM CDCIE Audio Chat", 1, false)});
|
||||
return session;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a org.jivesoftware.jingleaudio.jspeex.AudioMediaSession with defined payload type, remote and local candidates
|
||||
*
|
||||
* @param payloadType Payload of the jmf
|
||||
* @param remote the remote information. The candidate that the jmf will be sent to.
|
||||
* @param local the local information. The candidate that will receive the jmf
|
||||
* @param locator media locator
|
||||
*/
|
||||
public AudioMediaSession(final PayloadType payloadType, final TransportCandidate remote,
|
||||
final TransportCandidate local, String locator, JingleSession jingleSession) {
|
||||
super(payloadType, remote, local, locator == null ? "dsound://" : locator, jingleSession);
|
||||
initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the Audio Channel to make it able to send and receive audio
|
||||
*/
|
||||
public void initialize() {
|
||||
|
||||
String ip;
|
||||
String localIp;
|
||||
int localPort;
|
||||
int remotePort;
|
||||
|
||||
if (this.getLocal().getSymmetric() != null) {
|
||||
ip = this.getLocal().getIp();
|
||||
localIp = this.getLocal().getLocalIp();
|
||||
localPort = getFreePort();
|
||||
remotePort = this.getLocal().getSymmetric().getPort();
|
||||
|
||||
LOGGER.debug(this.getLocal().getConnection() + " " + ip + ": " + localPort + "->" + remotePort);
|
||||
|
||||
}
|
||||
else {
|
||||
ip = this.getRemote().getIp();
|
||||
localIp = this.getLocal().getLocalIp();
|
||||
localPort = this.getLocal().getPort();
|
||||
remotePort = this.getRemote().getPort();
|
||||
}
|
||||
|
||||
try {
|
||||
mediaSession = createSession(localIp, localPort, ip, remotePort, this, 2, false, true);
|
||||
}
|
||||
catch (NoProcessorException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (UnsupportedFormatException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (GeneralSecurityException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts transmission and for NAT Traversal reasons start receiving also.
|
||||
*/
|
||||
public void startTrasmit() {
|
||||
try {
|
||||
LOGGER.debug("start");
|
||||
mediaSession.start(true);
|
||||
this.mediaReceived("");
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set transmit activity. If the active is true, the instance should trasmit.
|
||||
* If it is set to false, the instance should pause transmit.
|
||||
*
|
||||
* @param active active state
|
||||
*/
|
||||
public void setTrasmit(boolean active) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf
|
||||
*/
|
||||
public void startReceive() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops transmission and for NAT Traversal reasons stop receiving also.
|
||||
*/
|
||||
public void stopTrasmit() {
|
||||
if (mediaSession != null)
|
||||
mediaSession.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf
|
||||
*/
|
||||
public void stopReceive() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
public void newStreamIdentified(StreamPlayer streamPlayer) {
|
||||
}
|
||||
|
||||
public void senderReportReceived(SenderReport report) {
|
||||
}
|
||||
|
||||
public void streamClosed(StreamPlayer stream, boolean timeout) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a free port we can use.
|
||||
*
|
||||
* @return A free port number.
|
||||
*/
|
||||
protected int getFreePort() {
|
||||
ServerSocket ss;
|
||||
int freePort = 0;
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
freePort = (int) (10000 + Math.round(Math.random() * 10000));
|
||||
freePort = freePort % 2 == 0 ? freePort : freePort + 1;
|
||||
try {
|
||||
ss = new ServerSocket(freePort);
|
||||
freePort = ss.getLocalPort();
|
||||
ss.close();
|
||||
return freePort;
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
try {
|
||||
ss = new ServerSocket(0);
|
||||
freePort = ss.getLocalPort();
|
||||
ss.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return freePort;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* <p/>
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
* <p/>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jivesoftware.smackx.jingle.mediaimpl.jspeex;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
import javax.media.NoProcessorException;
|
||||
import javax.media.format.UnsupportedFormatException;
|
||||
import javax.media.rtp.rtcp.SenderReport;
|
||||
import javax.media.rtp.rtcp.SourceDescription;
|
||||
|
||||
import mil.jfcom.cie.media.session.MediaSession;
|
||||
import mil.jfcom.cie.media.session.MediaSessionListener;
|
||||
import mil.jfcom.cie.media.session.StreamPlayer;
|
||||
import mil.jfcom.cie.media.srtp.packetizer.SpeexFormat;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
import org.jivesoftware.smackx.jingle.SmackLogger;
|
||||
import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
|
||||
import org.jivesoftware.smackx.jingle.media.PayloadType;
|
||||
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
|
||||
|
||||
/**
|
||||
* This Class implements a complete JingleMediaSession.
|
||||
* It sould be used to transmit and receive audio captured from the Mic.
|
||||
* This Class should be automaticly controlled by JingleSession.
|
||||
* But you could also use in any VOIP application.
|
||||
* For better NAT Traversal support this implementation don't support only receive or only transmit.
|
||||
* To receive you MUST transmit. So the only implemented and functionally methods are startTransmit() and stopTransmit()
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
|
||||
public class AudioMediaSession extends JingleMediaSession implements MediaSessionListener {
|
||||
|
||||
private static final SmackLogger LOGGER = SmackLogger.getLogger(AudioMediaSession.class);
|
||||
|
||||
private MediaSession mediaSession;
|
||||
|
||||
/**
|
||||
* Create a Session using Speex Codec
|
||||
*
|
||||
* @param localhost localHost
|
||||
* @param localPort localPort
|
||||
* @param remoteHost remoteHost
|
||||
* @param remotePort remotePort
|
||||
* @param eventHandler eventHandler
|
||||
* @param quality quality
|
||||
* @param secure secure
|
||||
* @param micOn micOn
|
||||
* @return MediaSession
|
||||
* @throws NoProcessorException
|
||||
* @throws UnsupportedFormatException
|
||||
* @throws IOException
|
||||
* @throws GeneralSecurityException
|
||||
*/
|
||||
public static MediaSession createSession(String localhost, int localPort, String remoteHost, int remotePort, MediaSessionListener eventHandler, int quality, boolean secure, boolean micOn) throws NoProcessorException, UnsupportedFormatException, IOException, GeneralSecurityException {
|
||||
|
||||
SpeexFormat.setFramesPerPacket(1);
|
||||
/**
|
||||
* The master key. Hardcoded for now.
|
||||
*/
|
||||
byte[] masterKey = new byte[]{(byte) 0xE1, (byte) 0xF9, 0x7A, 0x0D, 0x3E, 0x01, (byte) 0x8B, (byte) 0xE0, (byte) 0xD6, 0x4F, (byte) 0xA3, 0x2C, 0x06, (byte) 0xDE, 0x41, 0x39};
|
||||
|
||||
/**
|
||||
* The master salt. Hardcoded for now.
|
||||
*/
|
||||
byte[] masterSalt = new byte[]{0x0E, (byte) 0xC6, 0x75, (byte) 0xAD, 0x49, (byte) 0x8A, (byte) 0xFE, (byte) 0xEB, (byte) 0xB6, (byte) 0x96, 0x0B, 0x3A, (byte) 0xAB, (byte) 0xE6};
|
||||
|
||||
DatagramSocket[] localPorts = MediaSession.getLocalPorts(InetAddress.getByName(localhost), localPort);
|
||||
MediaSession session = MediaSession.createInstance(remoteHost, remotePort, localPorts, quality, secure, masterKey, masterSalt);
|
||||
session.setListener(eventHandler);
|
||||
|
||||
session.setSourceDescription(new SourceDescription[]{new SourceDescription(SourceDescription.SOURCE_DESC_NAME, "Superman", 1, false), new SourceDescription(SourceDescription.SOURCE_DESC_EMAIL, "cdcie.tester@je.jfcom.mil", 1, false), new SourceDescription(SourceDescription.SOURCE_DESC_LOC, InetAddress.getByName(localhost) + " Port " + session.getLocalDataPort(), 1, false), new SourceDescription(SourceDescription.SOURCE_DESC_TOOL, "JFCOM CDCIE Audio Chat", 1, false)});
|
||||
return session;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a org.jivesoftware.jingleaudio.jspeex.AudioMediaSession with defined payload type, remote and local candidates
|
||||
*
|
||||
* @param payloadType Payload of the jmf
|
||||
* @param remote the remote information. The candidate that the jmf will be sent to.
|
||||
* @param local the local information. The candidate that will receive the jmf
|
||||
* @param locator media locator
|
||||
*/
|
||||
public AudioMediaSession(final PayloadType payloadType, final TransportCandidate remote,
|
||||
final TransportCandidate local, String locator, JingleSession jingleSession) {
|
||||
super(payloadType, remote, local, locator == null ? "dsound://" : locator, jingleSession);
|
||||
initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the Audio Channel to make it able to send and receive audio
|
||||
*/
|
||||
public void initialize() {
|
||||
|
||||
String ip;
|
||||
String localIp;
|
||||
int localPort;
|
||||
int remotePort;
|
||||
|
||||
if (this.getLocal().getSymmetric() != null) {
|
||||
ip = this.getLocal().getIp();
|
||||
localIp = this.getLocal().getLocalIp();
|
||||
localPort = getFreePort();
|
||||
remotePort = this.getLocal().getSymmetric().getPort();
|
||||
|
||||
LOGGER.debug(this.getLocal().getConnection() + " " + ip + ": " + localPort + "->" + remotePort);
|
||||
|
||||
}
|
||||
else {
|
||||
ip = this.getRemote().getIp();
|
||||
localIp = this.getLocal().getLocalIp();
|
||||
localPort = this.getLocal().getPort();
|
||||
remotePort = this.getRemote().getPort();
|
||||
}
|
||||
|
||||
try {
|
||||
mediaSession = createSession(localIp, localPort, ip, remotePort, this, 2, false, true);
|
||||
}
|
||||
catch (NoProcessorException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (UnsupportedFormatException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (GeneralSecurityException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts transmission and for NAT Traversal reasons start receiving also.
|
||||
*/
|
||||
public void startTrasmit() {
|
||||
try {
|
||||
LOGGER.debug("start");
|
||||
mediaSession.start(true);
|
||||
this.mediaReceived("");
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set transmit activity. If the active is true, the instance should trasmit.
|
||||
* If it is set to false, the instance should pause transmit.
|
||||
*
|
||||
* @param active active state
|
||||
*/
|
||||
public void setTrasmit(boolean active) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf
|
||||
*/
|
||||
public void startReceive() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops transmission and for NAT Traversal reasons stop receiving also.
|
||||
*/
|
||||
public void stopTrasmit() {
|
||||
if (mediaSession != null)
|
||||
mediaSession.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf
|
||||
*/
|
||||
public void stopReceive() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
public void newStreamIdentified(StreamPlayer streamPlayer) {
|
||||
}
|
||||
|
||||
public void senderReportReceived(SenderReport report) {
|
||||
}
|
||||
|
||||
public void streamClosed(StreamPlayer stream, boolean timeout) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a free port we can use.
|
||||
*
|
||||
* @return A free port number.
|
||||
*/
|
||||
protected int getFreePort() {
|
||||
ServerSocket ss;
|
||||
int freePort = 0;
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
freePort = (int) (10000 + Math.round(Math.random() * 10000));
|
||||
freePort = freePort % 2 == 0 ? freePort : freePort + 1;
|
||||
try {
|
||||
ss = new ServerSocket(freePort);
|
||||
freePort = ss.getLocalPort();
|
||||
ss.close();
|
||||
return freePort;
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
try {
|
||||
ss = new ServerSocket(0);
|
||||
freePort = ss.getLocalPort();
|
||||
ss.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return freePort;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,131 +1,131 @@
|
|||
/**
|
||||
* <p/>
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
* <p/>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.mediaimpl.jspeex;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
import org.jivesoftware.smackx.jingle.SmackLogger;
|
||||
import org.jivesoftware.smackx.jingle.media.JingleMediaManager;
|
||||
import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
|
||||
import org.jivesoftware.smackx.jingle.media.PayloadType;
|
||||
import org.jivesoftware.smackx.jingle.mediaimpl.JMFInit;
|
||||
import org.jivesoftware.smackx.jingle.nat.JingleTransportManager;
|
||||
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
|
||||
|
||||
/**
|
||||
* Implements a jingleMediaManager using JMF based API and JSpeex.
|
||||
* It supports Speex codec.
|
||||
* <i>This API only currently works on windows.</i>
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public class SpeexMediaManager extends JingleMediaManager {
|
||||
|
||||
private static final SmackLogger LOGGER = SmackLogger.getLogger(SpeexMediaManager.class);
|
||||
|
||||
public static final String MEDIA_NAME = "Speex";
|
||||
|
||||
private List<PayloadType> payloads = new ArrayList<PayloadType>();
|
||||
|
||||
public SpeexMediaManager(JingleTransportManager transportManager) {
|
||||
super(transportManager);
|
||||
setupPayloads();
|
||||
setupJMF();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new jingleMediaSession
|
||||
*
|
||||
* @param payloadType payloadType
|
||||
* @param remote remote Candidate
|
||||
* @param local local Candidate
|
||||
* @return JingleMediaSession
|
||||
*/
|
||||
public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) {
|
||||
return new AudioMediaSession(payloadType, remote, local, null,null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup API supported Payloads
|
||||
*/
|
||||
private void setupPayloads() {
|
||||
payloads.add(new PayloadType.Audio(15, "speex"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all supported Payloads for this Manager
|
||||
*
|
||||
* @return The Payload List
|
||||
*/
|
||||
public List<PayloadType> getPayloads() {
|
||||
return payloads;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs JMFInit the first time the application is started so that capture
|
||||
* devices are properly detected and initialized by JMF.
|
||||
*/
|
||||
public static void setupJMF() {
|
||||
// .jmf is the place where we store the jmf.properties file used
|
||||
// by JMF. if the directory does not exist or it does not contain
|
||||
// a jmf.properties file. or if the jmf.properties file has 0 length
|
||||
// then this is the first time we're running and should continue to
|
||||
// with JMFInit
|
||||
String homeDir = System.getProperty("user.home");
|
||||
File jmfDir = new File(homeDir, ".jmf");
|
||||
String classpath = System.getProperty("java.class.path");
|
||||
classpath += System.getProperty("path.separator")
|
||||
+ jmfDir.getAbsolutePath();
|
||||
System.setProperty("java.class.path", classpath);
|
||||
|
||||
if (!jmfDir.exists())
|
||||
jmfDir.mkdir();
|
||||
|
||||
File jmfProperties = new File(jmfDir, "jmf.properties");
|
||||
|
||||
if (!jmfProperties.exists()) {
|
||||
try {
|
||||
jmfProperties.createNewFile();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
LOGGER.debug("Failed to create jmf.properties");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// if we're running on linux checkout that libjmutil.so is where it
|
||||
// should be and put it there.
|
||||
runLinuxPreInstall();
|
||||
|
||||
if (jmfProperties.length() == 0) {
|
||||
new JMFInit(null, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void runLinuxPreInstall() {
|
||||
// @TODO Implement Linux Pre-Install
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return MEDIA_NAME;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* <p/>
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
* <p/>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.mediaimpl.jspeex;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
import org.jivesoftware.smackx.jingle.SmackLogger;
|
||||
import org.jivesoftware.smackx.jingle.media.JingleMediaManager;
|
||||
import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
|
||||
import org.jivesoftware.smackx.jingle.media.PayloadType;
|
||||
import org.jivesoftware.smackx.jingle.mediaimpl.JMFInit;
|
||||
import org.jivesoftware.smackx.jingle.nat.JingleTransportManager;
|
||||
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
|
||||
|
||||
/**
|
||||
* Implements a jingleMediaManager using JMF based API and JSpeex.
|
||||
* It supports Speex codec.
|
||||
* <i>This API only currently works on windows.</i>
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public class SpeexMediaManager extends JingleMediaManager {
|
||||
|
||||
private static final SmackLogger LOGGER = SmackLogger.getLogger(SpeexMediaManager.class);
|
||||
|
||||
public static final String MEDIA_NAME = "Speex";
|
||||
|
||||
private List<PayloadType> payloads = new ArrayList<PayloadType>();
|
||||
|
||||
public SpeexMediaManager(JingleTransportManager transportManager) {
|
||||
super(transportManager);
|
||||
setupPayloads();
|
||||
setupJMF();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new jingleMediaSession
|
||||
*
|
||||
* @param payloadType payloadType
|
||||
* @param remote remote Candidate
|
||||
* @param local local Candidate
|
||||
* @return JingleMediaSession
|
||||
*/
|
||||
public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) {
|
||||
return new AudioMediaSession(payloadType, remote, local, null,null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup API supported Payloads
|
||||
*/
|
||||
private void setupPayloads() {
|
||||
payloads.add(new PayloadType.Audio(15, "speex"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all supported Payloads for this Manager
|
||||
*
|
||||
* @return The Payload List
|
||||
*/
|
||||
public List<PayloadType> getPayloads() {
|
||||
return payloads;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs JMFInit the first time the application is started so that capture
|
||||
* devices are properly detected and initialized by JMF.
|
||||
*/
|
||||
public static void setupJMF() {
|
||||
// .jmf is the place where we store the jmf.properties file used
|
||||
// by JMF. if the directory does not exist or it does not contain
|
||||
// a jmf.properties file. or if the jmf.properties file has 0 length
|
||||
// then this is the first time we're running and should continue to
|
||||
// with JMFInit
|
||||
String homeDir = System.getProperty("user.home");
|
||||
File jmfDir = new File(homeDir, ".jmf");
|
||||
String classpath = System.getProperty("java.class.path");
|
||||
classpath += System.getProperty("path.separator")
|
||||
+ jmfDir.getAbsolutePath();
|
||||
System.setProperty("java.class.path", classpath);
|
||||
|
||||
if (!jmfDir.exists())
|
||||
jmfDir.mkdir();
|
||||
|
||||
File jmfProperties = new File(jmfDir, "jmf.properties");
|
||||
|
||||
if (!jmfProperties.exists()) {
|
||||
try {
|
||||
jmfProperties.createNewFile();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
LOGGER.debug("Failed to create jmf.properties");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// if we're running on linux checkout that libjmutil.so is where it
|
||||
// should be and put it there.
|
||||
runLinuxPreInstall();
|
||||
|
||||
if (jmfProperties.length() == 0) {
|
||||
new JMFInit(null, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void runLinuxPreInstall() {
|
||||
// @TODO Implement Linux Pre-Install
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return MEDIA_NAME;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,154 +12,154 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.SocketException;
|
||||
|
||||
/**
|
||||
* UDP Image Receiver.
|
||||
* It uses PNG Tiles into UDP packets.
|
||||
*
|
||||
* @author Thiago Rocha Camargo
|
||||
*/
|
||||
public class ImageReceiver extends Canvas {
|
||||
|
||||
private static final long serialVersionUID = -7000112305305269025L;
|
||||
private boolean on = true;
|
||||
private DatagramSocket socket;
|
||||
private BufferedImage tiles[][];
|
||||
private static final int tileWidth = ImageTransmitter.tileWidth;
|
||||
private InetAddress localHost;
|
||||
private InetAddress remoteHost;
|
||||
private int localPort;
|
||||
private int remotePort;
|
||||
private ImageDecoder decoder;
|
||||
|
||||
public ImageReceiver(final InetAddress remoteHost, final int remotePort, final int localPort, int width, int height) {
|
||||
tiles = new BufferedImage[width][height];
|
||||
|
||||
try {
|
||||
|
||||
socket = new DatagramSocket(localPort);
|
||||
localHost = socket.getLocalAddress();
|
||||
this.remoteHost = remoteHost;
|
||||
this.remotePort = remotePort;
|
||||
this.localPort = localPort;
|
||||
this.decoder = new DefaultDecoder();
|
||||
|
||||
new Thread(new Runnable() {
|
||||
public void run() {
|
||||
byte buf[] = new byte[1024];
|
||||
DatagramPacket p = new DatagramPacket(buf, 1024);
|
||||
try {
|
||||
while (on) {
|
||||
socket.receive(p);
|
||||
|
||||
int length = p.getLength();
|
||||
|
||||
BufferedImage bufferedImage = decoder.decode(new ByteArrayInputStream(p.getData(), 0, length - 2));
|
||||
|
||||
if (bufferedImage != null) {
|
||||
|
||||
int x = p.getData()[length - 2];
|
||||
int y = p.getData()[length - 1];
|
||||
|
||||
drawTile(x, y, bufferedImage);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
|
||||
new Thread(new Runnable() {
|
||||
public void run() {
|
||||
byte buf[] = new byte[1024];
|
||||
DatagramPacket p = new DatagramPacket(buf, 1024);
|
||||
try {
|
||||
while (on) {
|
||||
|
||||
p.setAddress(remoteHost);
|
||||
p.setPort(remotePort);
|
||||
socket.send(p);
|
||||
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
|
||||
}
|
||||
catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.setSize(width, height);
|
||||
}
|
||||
|
||||
public InetAddress getLocalHost() {
|
||||
return localHost;
|
||||
}
|
||||
|
||||
public InetAddress getRemoteHost() {
|
||||
return remoteHost;
|
||||
}
|
||||
|
||||
public int getLocalPort() {
|
||||
return localPort;
|
||||
}
|
||||
|
||||
public int getRemotePort() {
|
||||
return remotePort;
|
||||
}
|
||||
|
||||
public DatagramSocket getDatagramSocket() {
|
||||
return socket;
|
||||
}
|
||||
|
||||
public void drawTile(int x, int y, BufferedImage bufferedImage) {
|
||||
tiles[x][y] = bufferedImage;
|
||||
//repaint(x * tileWidth, y * tileWidth, tileWidth, tileWidth);
|
||||
this.getGraphics().drawImage(bufferedImage, tileWidth * x, tileWidth * y, this);
|
||||
}
|
||||
|
||||
public void paint(Graphics g) {
|
||||
for (int i = 0; i < tiles.length; i++) {
|
||||
for (int j = 0; j < tiles[0].length; j++) {
|
||||
g.drawImage(tiles[i][j], tileWidth * i, tileWidth * j, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ImageDecoder getDecoder() {
|
||||
return decoder;
|
||||
}
|
||||
|
||||
public void setDecoder(ImageDecoder decoder) {
|
||||
this.decoder = decoder;
|
||||
}
|
||||
|
||||
public void stop(){
|
||||
this.on=false;
|
||||
socket.close();
|
||||
}
|
||||
}
|
||||
package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.SocketException;
|
||||
|
||||
/**
|
||||
* UDP Image Receiver.
|
||||
* It uses PNG Tiles into UDP packets.
|
||||
*
|
||||
* @author Thiago Rocha Camargo
|
||||
*/
|
||||
public class ImageReceiver extends Canvas {
|
||||
|
||||
private static final long serialVersionUID = -7000112305305269025L;
|
||||
private boolean on = true;
|
||||
private DatagramSocket socket;
|
||||
private BufferedImage tiles[][];
|
||||
private static final int tileWidth = ImageTransmitter.tileWidth;
|
||||
private InetAddress localHost;
|
||||
private InetAddress remoteHost;
|
||||
private int localPort;
|
||||
private int remotePort;
|
||||
private ImageDecoder decoder;
|
||||
|
||||
public ImageReceiver(final InetAddress remoteHost, final int remotePort, final int localPort, int width, int height) {
|
||||
tiles = new BufferedImage[width][height];
|
||||
|
||||
try {
|
||||
|
||||
socket = new DatagramSocket(localPort);
|
||||
localHost = socket.getLocalAddress();
|
||||
this.remoteHost = remoteHost;
|
||||
this.remotePort = remotePort;
|
||||
this.localPort = localPort;
|
||||
this.decoder = new DefaultDecoder();
|
||||
|
||||
new Thread(new Runnable() {
|
||||
public void run() {
|
||||
byte buf[] = new byte[1024];
|
||||
DatagramPacket p = new DatagramPacket(buf, 1024);
|
||||
try {
|
||||
while (on) {
|
||||
socket.receive(p);
|
||||
|
||||
int length = p.getLength();
|
||||
|
||||
BufferedImage bufferedImage = decoder.decode(new ByteArrayInputStream(p.getData(), 0, length - 2));
|
||||
|
||||
if (bufferedImage != null) {
|
||||
|
||||
int x = p.getData()[length - 2];
|
||||
int y = p.getData()[length - 1];
|
||||
|
||||
drawTile(x, y, bufferedImage);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
|
||||
new Thread(new Runnable() {
|
||||
public void run() {
|
||||
byte buf[] = new byte[1024];
|
||||
DatagramPacket p = new DatagramPacket(buf, 1024);
|
||||
try {
|
||||
while (on) {
|
||||
|
||||
p.setAddress(remoteHost);
|
||||
p.setPort(remotePort);
|
||||
socket.send(p);
|
||||
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
|
||||
}
|
||||
catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.setSize(width, height);
|
||||
}
|
||||
|
||||
public InetAddress getLocalHost() {
|
||||
return localHost;
|
||||
}
|
||||
|
||||
public InetAddress getRemoteHost() {
|
||||
return remoteHost;
|
||||
}
|
||||
|
||||
public int getLocalPort() {
|
||||
return localPort;
|
||||
}
|
||||
|
||||
public int getRemotePort() {
|
||||
return remotePort;
|
||||
}
|
||||
|
||||
public DatagramSocket getDatagramSocket() {
|
||||
return socket;
|
||||
}
|
||||
|
||||
public void drawTile(int x, int y, BufferedImage bufferedImage) {
|
||||
tiles[x][y] = bufferedImage;
|
||||
//repaint(x * tileWidth, y * tileWidth, tileWidth, tileWidth);
|
||||
this.getGraphics().drawImage(bufferedImage, tileWidth * x, tileWidth * y, this);
|
||||
}
|
||||
|
||||
public void paint(Graphics g) {
|
||||
for (int i = 0; i < tiles.length; i++) {
|
||||
for (int j = 0; j < tiles[0].length; j++) {
|
||||
g.drawImage(tiles[i][j], tileWidth * i, tileWidth * j, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ImageDecoder getDecoder() {
|
||||
return decoder;
|
||||
}
|
||||
|
||||
public void setDecoder(ImageDecoder decoder) {
|
||||
this.decoder = decoder;
|
||||
}
|
||||
|
||||
public void stop(){
|
||||
this.on=false;
|
||||
socket.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,207 +12,207 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api;
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Robot;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.PixelGrabber;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.SmackLogger;
|
||||
|
||||
/**
|
||||
* UDP Image Receiver.
|
||||
* It uses PNG Tiles into UDP packets.
|
||||
*
|
||||
* @author Thiago Rocha Camargo
|
||||
*/
|
||||
public class ImageTransmitter implements Runnable {
|
||||
|
||||
private static final SmackLogger LOGGER = SmackLogger.getLogger(ImageTransmitter.class);
|
||||
|
||||
private Robot robot;
|
||||
private InetAddress localHost;
|
||||
private InetAddress remoteHost;
|
||||
private int localPort;
|
||||
private int remotePort;
|
||||
public static final int tileWidth = 25;
|
||||
private boolean on = true;
|
||||
private boolean transmit = false;
|
||||
private DatagramSocket socket;
|
||||
private Rectangle area;
|
||||
private int tiles[][][];
|
||||
private int maxI;
|
||||
private int maxJ;
|
||||
private ImageEncoder encoder;
|
||||
public final static int KEYFRAME = 10;
|
||||
|
||||
public ImageTransmitter(DatagramSocket socket, InetAddress remoteHost, int remotePort, Rectangle area) {
|
||||
|
||||
try {
|
||||
robot = new Robot();
|
||||
|
||||
maxI = (int) Math.ceil(area.getWidth() / tileWidth);
|
||||
maxJ = (int) Math.ceil(area.getHeight() / tileWidth);
|
||||
|
||||
tiles = new int[maxI][maxJ][tileWidth * tileWidth];
|
||||
|
||||
this.area = area;
|
||||
this.socket = socket;
|
||||
localHost = socket.getLocalAddress();
|
||||
localPort = socket.getLocalPort();
|
||||
this.remoteHost = remoteHost;
|
||||
this.remotePort = remotePort;
|
||||
this.encoder = new DefaultEncoder();
|
||||
|
||||
transmit = true;
|
||||
|
||||
}
|
||||
catch (AWTException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void start() {
|
||||
byte buf[] = new byte[1024];
|
||||
final DatagramPacket p = new DatagramPacket(buf, 1024);
|
||||
|
||||
int keyframe = 0;
|
||||
|
||||
while (on) {
|
||||
if (transmit) {
|
||||
|
||||
BufferedImage capture = robot.createScreenCapture(area);
|
||||
|
||||
QuantizeFilter filter = new QuantizeFilter();
|
||||
capture = filter.filter(capture, null);
|
||||
|
||||
long trace = System.currentTimeMillis();
|
||||
|
||||
if (++keyframe > KEYFRAME) {
|
||||
keyframe = 0;
|
||||
}
|
||||
LOGGER.debug("KEYFRAME:" + keyframe);
|
||||
|
||||
for (int i = 0; i < maxI; i++) {
|
||||
for (int j = 0; j < maxJ; j++) {
|
||||
|
||||
final BufferedImage bufferedImage = capture.getSubimage(i * tileWidth, j * tileWidth, tileWidth, tileWidth);
|
||||
|
||||
int pixels[] = new int[tileWidth * tileWidth];
|
||||
|
||||
PixelGrabber pg = new PixelGrabber(bufferedImage, 0, 0, tileWidth, tileWidth, pixels, 0, tileWidth);
|
||||
|
||||
try {
|
||||
if (pg.grabPixels()) {
|
||||
|
||||
if (keyframe == KEYFRAME || !Arrays.equals(tiles[i][j], pixels)) {
|
||||
|
||||
ByteArrayOutputStream baos = encoder.encode(bufferedImage);
|
||||
|
||||
if (baos != null) {
|
||||
|
||||
try {
|
||||
|
||||
Thread.sleep(1);
|
||||
|
||||
baos.write(i);
|
||||
baos.write(j);
|
||||
|
||||
byte[] bytesOut = baos.toByteArray();
|
||||
|
||||
if (bytesOut.length > 1000)
|
||||
LOGGER.error("Bytes out > 1000. Equals " + bytesOut.length);
|
||||
|
||||
p.setData(bytesOut);
|
||||
p.setAddress(remoteHost);
|
||||
p.setPort(remotePort);
|
||||
|
||||
try {
|
||||
socket.send(p);
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
tiles[i][j] = pixels;
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trace = (System.currentTimeMillis() - trace);
|
||||
LOGGER.debug("Loop Time:" + trace);
|
||||
|
||||
if (trace < 500) {
|
||||
try {
|
||||
Thread.sleep(500 - trace);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Transmit Enabled/Disabled
|
||||
*
|
||||
* @param transmit boolean Enabled/Disabled
|
||||
*/
|
||||
public void setTransmit(boolean transmit) {
|
||||
this.transmit = transmit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the encoder used to encode Images Tiles
|
||||
*
|
||||
* @return encoder
|
||||
*/
|
||||
public ImageEncoder getEncoder() {
|
||||
return encoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the encoder used to encode Image Tiles
|
||||
*
|
||||
* @param encoder encoder
|
||||
*/
|
||||
public void setEncoder(ImageEncoder encoder) {
|
||||
this.encoder = encoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops Transmitter
|
||||
*/
|
||||
public void stop() {
|
||||
this.transmit = false;
|
||||
this.on = false;
|
||||
socket.close();
|
||||
}
|
||||
}
|
||||
package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api;
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Robot;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.PixelGrabber;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.SmackLogger;
|
||||
|
||||
/**
|
||||
* UDP Image Receiver.
|
||||
* It uses PNG Tiles into UDP packets.
|
||||
*
|
||||
* @author Thiago Rocha Camargo
|
||||
*/
|
||||
public class ImageTransmitter implements Runnable {
|
||||
|
||||
private static final SmackLogger LOGGER = SmackLogger.getLogger(ImageTransmitter.class);
|
||||
|
||||
private Robot robot;
|
||||
private InetAddress localHost;
|
||||
private InetAddress remoteHost;
|
||||
private int localPort;
|
||||
private int remotePort;
|
||||
public static final int tileWidth = 25;
|
||||
private boolean on = true;
|
||||
private boolean transmit = false;
|
||||
private DatagramSocket socket;
|
||||
private Rectangle area;
|
||||
private int tiles[][][];
|
||||
private int maxI;
|
||||
private int maxJ;
|
||||
private ImageEncoder encoder;
|
||||
public final static int KEYFRAME = 10;
|
||||
|
||||
public ImageTransmitter(DatagramSocket socket, InetAddress remoteHost, int remotePort, Rectangle area) {
|
||||
|
||||
try {
|
||||
robot = new Robot();
|
||||
|
||||
maxI = (int) Math.ceil(area.getWidth() / tileWidth);
|
||||
maxJ = (int) Math.ceil(area.getHeight() / tileWidth);
|
||||
|
||||
tiles = new int[maxI][maxJ][tileWidth * tileWidth];
|
||||
|
||||
this.area = area;
|
||||
this.socket = socket;
|
||||
localHost = socket.getLocalAddress();
|
||||
localPort = socket.getLocalPort();
|
||||
this.remoteHost = remoteHost;
|
||||
this.remotePort = remotePort;
|
||||
this.encoder = new DefaultEncoder();
|
||||
|
||||
transmit = true;
|
||||
|
||||
}
|
||||
catch (AWTException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void start() {
|
||||
byte buf[] = new byte[1024];
|
||||
final DatagramPacket p = new DatagramPacket(buf, 1024);
|
||||
|
||||
int keyframe = 0;
|
||||
|
||||
while (on) {
|
||||
if (transmit) {
|
||||
|
||||
BufferedImage capture = robot.createScreenCapture(area);
|
||||
|
||||
QuantizeFilter filter = new QuantizeFilter();
|
||||
capture = filter.filter(capture, null);
|
||||
|
||||
long trace = System.currentTimeMillis();
|
||||
|
||||
if (++keyframe > KEYFRAME) {
|
||||
keyframe = 0;
|
||||
}
|
||||
LOGGER.debug("KEYFRAME:" + keyframe);
|
||||
|
||||
for (int i = 0; i < maxI; i++) {
|
||||
for (int j = 0; j < maxJ; j++) {
|
||||
|
||||
final BufferedImage bufferedImage = capture.getSubimage(i * tileWidth, j * tileWidth, tileWidth, tileWidth);
|
||||
|
||||
int pixels[] = new int[tileWidth * tileWidth];
|
||||
|
||||
PixelGrabber pg = new PixelGrabber(bufferedImage, 0, 0, tileWidth, tileWidth, pixels, 0, tileWidth);
|
||||
|
||||
try {
|
||||
if (pg.grabPixels()) {
|
||||
|
||||
if (keyframe == KEYFRAME || !Arrays.equals(tiles[i][j], pixels)) {
|
||||
|
||||
ByteArrayOutputStream baos = encoder.encode(bufferedImage);
|
||||
|
||||
if (baos != null) {
|
||||
|
||||
try {
|
||||
|
||||
Thread.sleep(1);
|
||||
|
||||
baos.write(i);
|
||||
baos.write(j);
|
||||
|
||||
byte[] bytesOut = baos.toByteArray();
|
||||
|
||||
if (bytesOut.length > 1000)
|
||||
LOGGER.error("Bytes out > 1000. Equals " + bytesOut.length);
|
||||
|
||||
p.setData(bytesOut);
|
||||
p.setAddress(remoteHost);
|
||||
p.setPort(remotePort);
|
||||
|
||||
try {
|
||||
socket.send(p);
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
tiles[i][j] = pixels;
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trace = (System.currentTimeMillis() - trace);
|
||||
LOGGER.debug("Loop Time:" + trace);
|
||||
|
||||
if (trace < 500) {
|
||||
try {
|
||||
Thread.sleep(500 - trace);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Transmit Enabled/Disabled
|
||||
*
|
||||
* @param transmit boolean Enabled/Disabled
|
||||
*/
|
||||
public void setTransmit(boolean transmit) {
|
||||
this.transmit = transmit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the encoder used to encode Images Tiles
|
||||
*
|
||||
* @return encoder
|
||||
*/
|
||||
public ImageEncoder getEncoder() {
|
||||
return encoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the encoder used to encode Image Tiles
|
||||
*
|
||||
* @param encoder encoder
|
||||
*/
|
||||
public void setEncoder(ImageEncoder encoder) {
|
||||
this.encoder = encoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops Transmitter
|
||||
*/
|
||||
public void stop() {
|
||||
this.transmit = false;
|
||||
this.on = false;
|
||||
socket.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
package org.jivesoftware.smackx.jingle.nat;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
|
||||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A Basic Jingle Transport Manager implementation.
|
||||
*
|
||||
*/
|
||||
public class BasicTransportManager extends JingleTransportManager{
|
||||
|
||||
protected TransportResolver createResolver(JingleSession session) {
|
||||
return new BasicResolver();
|
||||
}
|
||||
}
|
||||
package org.jivesoftware.smackx.jingle.nat;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
|
||||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A Basic Jingle Transport Manager implementation.
|
||||
*
|
||||
*/
|
||||
public class BasicTransportManager extends JingleTransportManager{
|
||||
|
||||
protected TransportResolver createResolver(JingleSession session) {
|
||||
return new BasicResolver();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,147 +1,147 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2003-2005 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.nat;
|
||||
|
||||
import org.jivesoftware.smack.Connection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Bridged Resolver use a RTPBridge Service to add a relayed candidate.
|
||||
* A very reliable solution for NAT Traversal.
|
||||
* <p/>
|
||||
* The resolver verify is the XMPP Server that the client is connected offer this service.
|
||||
* If the server supports, a candidate is requested from the service.
|
||||
* The resolver adds this candidate
|
||||
*/
|
||||
public class BridgedResolver extends TransportResolver {
|
||||
|
||||
Connection connection;
|
||||
|
||||
Random random = new Random();
|
||||
|
||||
long sid;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* A Bridged Resolver need a Connection to connect to a RTP Bridge.
|
||||
*/
|
||||
public BridgedResolver(Connection connection) {
|
||||
super();
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve Bridged Candidate.
|
||||
* <p/>
|
||||
* The BridgedResolver takes the IP addresse and ports of a jmf proxy service.
|
||||
*/
|
||||
public synchronized void resolve(JingleSession session) throws XMPPException {
|
||||
|
||||
setResolveInit();
|
||||
|
||||
clearCandidates();
|
||||
|
||||
sid = Math.abs(random.nextLong());
|
||||
|
||||
RTPBridge rtpBridge = RTPBridge.getRTPBridge(connection, String.valueOf(sid));
|
||||
|
||||
String localIp = getLocalHost();
|
||||
|
||||
TransportCandidate localCandidate = new TransportCandidate.Fixed(
|
||||
rtpBridge.getIp(), rtpBridge.getPortA());
|
||||
localCandidate.setLocalIp(localIp);
|
||||
|
||||
TransportCandidate remoteCandidate = new TransportCandidate.Fixed(
|
||||
rtpBridge.getIp(), rtpBridge.getPortB());
|
||||
remoteCandidate.setLocalIp(localIp);
|
||||
|
||||
localCandidate.setSymmetric(remoteCandidate);
|
||||
remoteCandidate.setSymmetric(localCandidate);
|
||||
|
||||
localCandidate.setPassword(rtpBridge.getPass());
|
||||
remoteCandidate.setPassword(rtpBridge.getPass());
|
||||
|
||||
localCandidate.setSessionId(rtpBridge.getSid());
|
||||
remoteCandidate.setSessionId(rtpBridge.getSid());
|
||||
|
||||
localCandidate.setConnection(this.connection);
|
||||
remoteCandidate.setConnection(this.connection);
|
||||
|
||||
addCandidate(localCandidate);
|
||||
|
||||
setResolveEnd();
|
||||
}
|
||||
|
||||
public void initialize() throws XMPPException {
|
||||
|
||||
clearCandidates();
|
||||
|
||||
if (!RTPBridge.serviceAvailable(connection)) {
|
||||
setInitialized();
|
||||
throw new XMPPException("No RTP Bridge service available");
|
||||
}
|
||||
setInitialized();
|
||||
|
||||
}
|
||||
|
||||
public void cancel() throws XMPPException {
|
||||
// Nothing to do here
|
||||
}
|
||||
|
||||
public static String getLocalHost() {
|
||||
Enumeration<NetworkInterface> ifaces = null;
|
||||
|
||||
try {
|
||||
ifaces = NetworkInterface.getNetworkInterfaces();
|
||||
}
|
||||
catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
while (ifaces.hasMoreElements()) {
|
||||
|
||||
NetworkInterface iface = ifaces.nextElement();
|
||||
Enumeration<InetAddress> iaddresses = iface.getInetAddresses();
|
||||
|
||||
while (iaddresses.hasMoreElements()) {
|
||||
InetAddress iaddress = iaddresses.nextElement();
|
||||
if (!iaddress.isLoopbackAddress() && !iaddress.isLinkLocalAddress() && !iaddress.isSiteLocalAddress() && !(iaddress instanceof Inet6Address)) {
|
||||
return iaddress.getHostAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return InetAddress.getLocalHost().getHostAddress();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return "127.0.0.1";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
*
|
||||
* Copyright 2003-2005 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.nat;
|
||||
|
||||
import org.jivesoftware.smack.Connection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Bridged Resolver use a RTPBridge Service to add a relayed candidate.
|
||||
* A very reliable solution for NAT Traversal.
|
||||
* <p/>
|
||||
* The resolver verify is the XMPP Server that the client is connected offer this service.
|
||||
* If the server supports, a candidate is requested from the service.
|
||||
* The resolver adds this candidate
|
||||
*/
|
||||
public class BridgedResolver extends TransportResolver {
|
||||
|
||||
Connection connection;
|
||||
|
||||
Random random = new Random();
|
||||
|
||||
long sid;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* A Bridged Resolver need a Connection to connect to a RTP Bridge.
|
||||
*/
|
||||
public BridgedResolver(Connection connection) {
|
||||
super();
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve Bridged Candidate.
|
||||
* <p/>
|
||||
* The BridgedResolver takes the IP addresse and ports of a jmf proxy service.
|
||||
*/
|
||||
public synchronized void resolve(JingleSession session) throws XMPPException {
|
||||
|
||||
setResolveInit();
|
||||
|
||||
clearCandidates();
|
||||
|
||||
sid = Math.abs(random.nextLong());
|
||||
|
||||
RTPBridge rtpBridge = RTPBridge.getRTPBridge(connection, String.valueOf(sid));
|
||||
|
||||
String localIp = getLocalHost();
|
||||
|
||||
TransportCandidate localCandidate = new TransportCandidate.Fixed(
|
||||
rtpBridge.getIp(), rtpBridge.getPortA());
|
||||
localCandidate.setLocalIp(localIp);
|
||||
|
||||
TransportCandidate remoteCandidate = new TransportCandidate.Fixed(
|
||||
rtpBridge.getIp(), rtpBridge.getPortB());
|
||||
remoteCandidate.setLocalIp(localIp);
|
||||
|
||||
localCandidate.setSymmetric(remoteCandidate);
|
||||
remoteCandidate.setSymmetric(localCandidate);
|
||||
|
||||
localCandidate.setPassword(rtpBridge.getPass());
|
||||
remoteCandidate.setPassword(rtpBridge.getPass());
|
||||
|
||||
localCandidate.setSessionId(rtpBridge.getSid());
|
||||
remoteCandidate.setSessionId(rtpBridge.getSid());
|
||||
|
||||
localCandidate.setConnection(this.connection);
|
||||
remoteCandidate.setConnection(this.connection);
|
||||
|
||||
addCandidate(localCandidate);
|
||||
|
||||
setResolveEnd();
|
||||
}
|
||||
|
||||
public void initialize() throws XMPPException {
|
||||
|
||||
clearCandidates();
|
||||
|
||||
if (!RTPBridge.serviceAvailable(connection)) {
|
||||
setInitialized();
|
||||
throw new XMPPException("No RTP Bridge service available");
|
||||
}
|
||||
setInitialized();
|
||||
|
||||
}
|
||||
|
||||
public void cancel() throws XMPPException {
|
||||
// Nothing to do here
|
||||
}
|
||||
|
||||
public static String getLocalHost() {
|
||||
Enumeration<NetworkInterface> ifaces = null;
|
||||
|
||||
try {
|
||||
ifaces = NetworkInterface.getNetworkInterfaces();
|
||||
}
|
||||
catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
while (ifaces.hasMoreElements()) {
|
||||
|
||||
NetworkInterface iface = ifaces.nextElement();
|
||||
Enumeration<InetAddress> iaddresses = iface.getInetAddresses();
|
||||
|
||||
while (iaddresses.hasMoreElements()) {
|
||||
InetAddress iaddress = iaddresses.nextElement();
|
||||
if (!iaddress.isLoopbackAddress() && !iaddress.isLinkLocalAddress() && !iaddress.isSiteLocalAddress() && !(iaddress instanceof Inet6Address)) {
|
||||
return iaddress.getHostAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return InetAddress.getLocalHost().getHostAddress();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return "127.0.0.1";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,80 +1,80 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.nat;
|
||||
|
||||
import org.jivesoftware.smack.Connection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
import org.jivesoftware.smackx.jingle.listeners.CreatedJingleSessionListener;
|
||||
import org.jivesoftware.smackx.jingle.listeners.JingleSessionListener;
|
||||
import org.jivesoftware.smackx.jingle.media.PayloadType;
|
||||
|
||||
/**
|
||||
* A Jingle Transport Manager implementation to be used for NAT Networks.
|
||||
* This kind of transport needs that the connected XMPP Server provide a Bridge Service. (http://www.jivesoftware.com/protocol/rtpbridge)
|
||||
* To relay the jmf outside the NAT.
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public class BridgedTransportManager extends JingleTransportManager implements JingleSessionListener, CreatedJingleSessionListener {
|
||||
|
||||
Connection xmppConnection;
|
||||
|
||||
public BridgedTransportManager(Connection xmppConnection) {
|
||||
super();
|
||||
this.xmppConnection = xmppConnection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the correspondent resolver
|
||||
*
|
||||
* @param session correspondent Jingle Session
|
||||
* @return resolver
|
||||
*/
|
||||
protected TransportResolver createResolver(JingleSession session) {
|
||||
BridgedResolver bridgedResolver = new BridgedResolver(this.xmppConnection);
|
||||
return bridgedResolver;
|
||||
}
|
||||
|
||||
// Implement a Session Listener to relay candidates after establishment
|
||||
|
||||
public void sessionEstablished(PayloadType pt, TransportCandidate rc, TransportCandidate lc, JingleSession jingleSession) {
|
||||
RTPBridge rtpBridge = RTPBridge.relaySession(lc.getConnection(), lc.getSessionId(), lc.getPassword(), rc, lc);
|
||||
}
|
||||
|
||||
public void sessionDeclined(String reason, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionRedirected(String redirection, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionClosed(String reason, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionClosedOnError(XMPPException e, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionMediaReceived(JingleSession jingleSession, String participant) {
|
||||
// Do Nothing
|
||||
}
|
||||
|
||||
// Session Created
|
||||
|
||||
public void sessionCreated(JingleSession jingleSession) {
|
||||
jingleSession.addListener(this);
|
||||
}
|
||||
}
|
||||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.nat;
|
||||
|
||||
import org.jivesoftware.smack.Connection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
import org.jivesoftware.smackx.jingle.listeners.CreatedJingleSessionListener;
|
||||
import org.jivesoftware.smackx.jingle.listeners.JingleSessionListener;
|
||||
import org.jivesoftware.smackx.jingle.media.PayloadType;
|
||||
|
||||
/**
|
||||
* A Jingle Transport Manager implementation to be used for NAT Networks.
|
||||
* This kind of transport needs that the connected XMPP Server provide a Bridge Service. (http://www.jivesoftware.com/protocol/rtpbridge)
|
||||
* To relay the jmf outside the NAT.
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public class BridgedTransportManager extends JingleTransportManager implements JingleSessionListener, CreatedJingleSessionListener {
|
||||
|
||||
Connection xmppConnection;
|
||||
|
||||
public BridgedTransportManager(Connection xmppConnection) {
|
||||
super();
|
||||
this.xmppConnection = xmppConnection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the correspondent resolver
|
||||
*
|
||||
* @param session correspondent Jingle Session
|
||||
* @return resolver
|
||||
*/
|
||||
protected TransportResolver createResolver(JingleSession session) {
|
||||
BridgedResolver bridgedResolver = new BridgedResolver(this.xmppConnection);
|
||||
return bridgedResolver;
|
||||
}
|
||||
|
||||
// Implement a Session Listener to relay candidates after establishment
|
||||
|
||||
public void sessionEstablished(PayloadType pt, TransportCandidate rc, TransportCandidate lc, JingleSession jingleSession) {
|
||||
RTPBridge rtpBridge = RTPBridge.relaySession(lc.getConnection(), lc.getSessionId(), lc.getPassword(), rc, lc);
|
||||
}
|
||||
|
||||
public void sessionDeclined(String reason, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionRedirected(String redirection, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionClosed(String reason, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionClosedOnError(XMPPException e, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionMediaReceived(JingleSession jingleSession, String participant) {
|
||||
// Do Nothing
|
||||
}
|
||||
|
||||
// Session Created
|
||||
|
||||
public void sessionCreated(JingleSession jingleSession) {
|
||||
jingleSession.addListener(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,4 +34,4 @@ public interface DatagramListener {
|
|||
*/
|
||||
public boolean datagramReceived(DatagramPacket datagramPacket);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,65 +1,65 @@
|
|||
package org.jivesoftware.smackx.jingle.nat;
|
||||
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smackx.jingle.ContentNegotiator;
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
import org.jivesoftware.smackx.jingle.listeners.CreatedJingleSessionListener;
|
||||
import org.jivesoftware.smackx.jingle.listeners.JingleSessionListener;
|
||||
import org.jivesoftware.smackx.jingle.media.PayloadType;
|
||||
|
||||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A Fixed Jingle Transport Manager implementation.
|
||||
*
|
||||
*/
|
||||
public class FixedTransportManager extends JingleTransportManager implements JingleSessionListener, CreatedJingleSessionListener {
|
||||
|
||||
FixedResolver resolver;
|
||||
|
||||
public FixedTransportManager(FixedResolver inResolver) {
|
||||
resolver = inResolver;
|
||||
}
|
||||
|
||||
protected TransportResolver createResolver(JingleSession session) {
|
||||
return resolver;
|
||||
}
|
||||
|
||||
public void sessionEstablished(PayloadType pt, TransportCandidate rc, TransportCandidate lc, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionDeclined(String reason, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionRedirected(String redirection, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionClosed(String reason, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionClosedOnError(XMPPException e, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionMediaReceived(JingleSession jingleSession, String participant) {
|
||||
// Do Nothing
|
||||
}
|
||||
|
||||
public void sessionCreated(JingleSession jingleSession) {
|
||||
jingleSession.addListener(this);
|
||||
}
|
||||
}
|
||||
package org.jivesoftware.smackx.jingle.nat;
|
||||
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smackx.jingle.ContentNegotiator;
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
import org.jivesoftware.smackx.jingle.listeners.CreatedJingleSessionListener;
|
||||
import org.jivesoftware.smackx.jingle.listeners.JingleSessionListener;
|
||||
import org.jivesoftware.smackx.jingle.media.PayloadType;
|
||||
|
||||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A Fixed Jingle Transport Manager implementation.
|
||||
*
|
||||
*/
|
||||
public class FixedTransportManager extends JingleTransportManager implements JingleSessionListener, CreatedJingleSessionListener {
|
||||
|
||||
FixedResolver resolver;
|
||||
|
||||
public FixedTransportManager(FixedResolver inResolver) {
|
||||
resolver = inResolver;
|
||||
}
|
||||
|
||||
protected TransportResolver createResolver(JingleSession session) {
|
||||
return resolver;
|
||||
}
|
||||
|
||||
public void sessionEstablished(PayloadType pt, TransportCandidate rc, TransportCandidate lc, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionDeclined(String reason, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionRedirected(String redirection, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionClosed(String reason, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionClosedOnError(XMPPException e, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionMediaReceived(JingleSession jingleSession, String participant) {
|
||||
// Do Nothing
|
||||
}
|
||||
|
||||
public void sessionCreated(JingleSession jingleSession) {
|
||||
jingleSession.addListener(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,4 +142,4 @@ public class HttpServer {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,278 +1,278 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2003-2005 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jivesoftware.smackx.jingle.nat;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import org.jivesoftware.smack.Connection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
import org.jivesoftware.smackx.jingle.SmackLogger;
|
||||
|
||||
import de.javawi.jstun.test.demo.ice.Candidate;
|
||||
import de.javawi.jstun.test.demo.ice.ICENegociator;
|
||||
import de.javawi.jstun.util.UtilityException;
|
||||
|
||||
/**
|
||||
* ICE Resolver for Jingle transport method that results in sending data between two entities using the Interactive Connectivity Establishment (ICE) methodology. (XEP-0176)
|
||||
* The goal of this resolver is to make possible to establish and manage out-of-band connections between two XMPP entities, even if they are behind Network Address Translators (NATs) or firewalls.
|
||||
* To use this resolver you must have a STUN Server and be in a non STUN blocked network. Or use a XMPP server with public IP detection Service.
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public class ICEResolver extends TransportResolver {
|
||||
|
||||
private static final SmackLogger LOGGER = SmackLogger.getLogger(ICEResolver.class);
|
||||
|
||||
Connection connection;
|
||||
Random random = new Random();
|
||||
long sid;
|
||||
String server;
|
||||
int port;
|
||||
static Map<String, ICENegociator> negociatorsMap = new HashMap<String, ICENegociator>();
|
||||
//ICENegociator iceNegociator = null;
|
||||
|
||||
public ICEResolver(Connection connection, String server, int port) {
|
||||
super();
|
||||
this.connection = connection;
|
||||
this.server = server;
|
||||
this.port = port;
|
||||
this.setType(Type.ice);
|
||||
}
|
||||
|
||||
public void initialize() throws XMPPException {
|
||||
if (!isResolving() && !isResolved()) {
|
||||
LOGGER.debug("Initialized");
|
||||
|
||||
// Negotiation with a STUN server for a set of interfaces is quite slow, but the results
|
||||
// never change over then instance of a JVM. To increase connection performance considerably
|
||||
// we now cache established/initialized negotiators for each STUN server, so that subsequent uses
|
||||
// of the STUN server are much, much faster.
|
||||
if (negociatorsMap.get(server) == null) {
|
||||
ICENegociator iceNegociator = new ICENegociator(server, port, (short) 1);
|
||||
negociatorsMap.put(server, iceNegociator);
|
||||
|
||||
// gather candidates
|
||||
iceNegociator.gatherCandidateAddresses();
|
||||
// priorize candidates
|
||||
iceNegociator.prioritizeCandidates();
|
||||
}
|
||||
|
||||
}
|
||||
this.setInitialized();
|
||||
}
|
||||
|
||||
public void cancel() throws XMPPException {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the IP and obtain a valid transport method.
|
||||
*/
|
||||
public synchronized void resolve(JingleSession session) throws XMPPException {
|
||||
this.setResolveInit();
|
||||
|
||||
for (TransportCandidate candidate : this.getCandidatesList()) {
|
||||
if (candidate instanceof ICECandidate) {
|
||||
ICECandidate iceCandidate = (ICECandidate) candidate;
|
||||
iceCandidate.removeCandidateEcho();
|
||||
}
|
||||
}
|
||||
|
||||
this.clear();
|
||||
|
||||
// Create a transport candidate for each ICE negotiator candidate we have.
|
||||
ICENegociator iceNegociator = negociatorsMap.get(server);
|
||||
for (Candidate candidate : iceNegociator.getSortedCandidates())
|
||||
try {
|
||||
Candidate.CandidateType type = candidate.getCandidateType();
|
||||
ICECandidate.Type iceType = ICECandidate.Type.local;
|
||||
if (type.equals(Candidate.CandidateType.ServerReflexive))
|
||||
iceType = ICECandidate.Type.srflx;
|
||||
else if (type.equals(Candidate.CandidateType.PeerReflexive))
|
||||
iceType = ICECandidate.Type.prflx;
|
||||
else if (type.equals(Candidate.CandidateType.Relayed))
|
||||
iceType = ICECandidate.Type.relay;
|
||||
else
|
||||
iceType = ICECandidate.Type.host;
|
||||
|
||||
// JBW/GW - 17JUL08: Figure out the zero-based NIC number for this candidate.
|
||||
short nicNum = 0;
|
||||
try {
|
||||
Enumeration<NetworkInterface> nics = NetworkInterface.getNetworkInterfaces();
|
||||
short i = 0;
|
||||
NetworkInterface nic = NetworkInterface.getByInetAddress(candidate.getAddress().getInetAddress());
|
||||
while(nics.hasMoreElements()) {
|
||||
NetworkInterface checkNIC = nics.nextElement();
|
||||
if (checkNIC.equals(nic)) {
|
||||
nicNum = i;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
} catch (SocketException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
TransportCandidate transportCandidate = new ICECandidate(candidate.getAddress().getInetAddress().getHostAddress(), 1, nicNum, String.valueOf(Math.abs(random.nextLong())), candidate.getPort(), "1", candidate.getPriority(), iceType);
|
||||
transportCandidate.setLocalIp(candidate.getBase().getAddress().getInetAddress().getHostAddress());
|
||||
transportCandidate.setPort(getFreePort());
|
||||
try {
|
||||
transportCandidate.addCandidateEcho(session);
|
||||
}
|
||||
catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.addCandidate(transportCandidate);
|
||||
|
||||
LOGGER.debug("Candidate addr: " + candidate.getAddress().getInetAddress() + "|" + candidate.getBase().getAddress().getInetAddress() + " Priority:" + candidate.getPriority());
|
||||
|
||||
}
|
||||
catch (UtilityException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// Get a Relay Candidate from XMPP Server
|
||||
|
||||
if (RTPBridge.serviceAvailable(connection)) {
|
||||
// try {
|
||||
|
||||
String localIp;
|
||||
int network;
|
||||
|
||||
|
||||
// JBW/GW - 17JUL08: ICENegotiator.getPublicCandidate() always returned null in JSTUN 1.7.0, and now the API doesn't exist in JSTUN 1.7.1
|
||||
// if (iceNegociator.getPublicCandidate() != null) {
|
||||
// localIp = iceNegociator.getPublicCandidate().getBase().getAddress().getInetAddress().getHostAddress();
|
||||
// network = iceNegociator.getPublicCandidate().getNetwork();
|
||||
// }
|
||||
// else {
|
||||
{
|
||||
localIp = BridgedResolver.getLocalHost();
|
||||
network = 0;
|
||||
}
|
||||
|
||||
sid = Math.abs(random.nextLong());
|
||||
|
||||
RTPBridge rtpBridge = RTPBridge.getRTPBridge(connection, String.valueOf(sid));
|
||||
|
||||
TransportCandidate localCandidate = new ICECandidate(
|
||||
rtpBridge.getIp(), 1, network, String.valueOf(Math.abs(random.nextLong())), rtpBridge.getPortA(), "1", 0, ICECandidate.Type.relay);
|
||||
localCandidate.setLocalIp(localIp);
|
||||
|
||||
TransportCandidate remoteCandidate = new ICECandidate(
|
||||
rtpBridge.getIp(), 1, network, String.valueOf(Math.abs(random.nextLong())), rtpBridge.getPortB(), "1", 0, ICECandidate.Type.relay);
|
||||
remoteCandidate.setLocalIp(localIp);
|
||||
|
||||
localCandidate.setSymmetric(remoteCandidate);
|
||||
remoteCandidate.setSymmetric(localCandidate);
|
||||
|
||||
localCandidate.setPassword(rtpBridge.getPass());
|
||||
remoteCandidate.setPassword(rtpBridge.getPass());
|
||||
|
||||
localCandidate.setSessionId(rtpBridge.getSid());
|
||||
remoteCandidate.setSessionId(rtpBridge.getSid());
|
||||
|
||||
localCandidate.setConnection(this.connection);
|
||||
remoteCandidate.setConnection(this.connection);
|
||||
|
||||
addCandidate(localCandidate);
|
||||
|
||||
// }
|
||||
// catch (UtilityException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// catch (UnknownHostException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
|
||||
// Get Public Candidate From XMPP Server
|
||||
|
||||
// JBW/GW - 17JUL08 - ICENegotiator.getPublicCandidate() always returned null in JSTUN 1.7.0, and now it doesn't exist in JSTUN 1.7.1
|
||||
// if (iceNegociator.getPublicCandidate() == null) {
|
||||
if (true) {
|
||||
|
||||
String publicIp = RTPBridge.getPublicIP(connection);
|
||||
|
||||
if (publicIp != null && !publicIp.equals("")) {
|
||||
|
||||
Enumeration<NetworkInterface> ifaces = null;
|
||||
|
||||
try {
|
||||
ifaces = NetworkInterface.getNetworkInterfaces();
|
||||
}
|
||||
catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// If detect this address in local machine, don't use it.
|
||||
|
||||
boolean found = false;
|
||||
|
||||
while (ifaces.hasMoreElements() && !false) {
|
||||
|
||||
NetworkInterface iface = ifaces.nextElement();
|
||||
Enumeration<InetAddress> iaddresses = iface.getInetAddresses();
|
||||
|
||||
while (iaddresses.hasMoreElements()) {
|
||||
InetAddress iaddress = iaddresses.nextElement();
|
||||
if (iaddress.getHostAddress().indexOf(publicIp) > -1) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
try {
|
||||
TransportCandidate publicCandidate = new ICECandidate(
|
||||
publicIp, 1, 0, String.valueOf(Math.abs(random.nextLong())), getFreePort(), "1", 0, ICECandidate.Type.srflx);
|
||||
publicCandidate.setLocalIp(InetAddress.getLocalHost().getHostAddress());
|
||||
|
||||
try {
|
||||
publicCandidate.addCandidateEcho(session);
|
||||
}
|
||||
catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
addCandidate(publicCandidate);
|
||||
}
|
||||
catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.setResolveEnd();
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
*
|
||||
* Copyright 2003-2005 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jivesoftware.smackx.jingle.nat;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import org.jivesoftware.smack.Connection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
import org.jivesoftware.smackx.jingle.SmackLogger;
|
||||
|
||||
import de.javawi.jstun.test.demo.ice.Candidate;
|
||||
import de.javawi.jstun.test.demo.ice.ICENegociator;
|
||||
import de.javawi.jstun.util.UtilityException;
|
||||
|
||||
/**
|
||||
* ICE Resolver for Jingle transport method that results in sending data between two entities using the Interactive Connectivity Establishment (ICE) methodology. (XEP-0176)
|
||||
* The goal of this resolver is to make possible to establish and manage out-of-band connections between two XMPP entities, even if they are behind Network Address Translators (NATs) or firewalls.
|
||||
* To use this resolver you must have a STUN Server and be in a non STUN blocked network. Or use a XMPP server with public IP detection Service.
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public class ICEResolver extends TransportResolver {
|
||||
|
||||
private static final SmackLogger LOGGER = SmackLogger.getLogger(ICEResolver.class);
|
||||
|
||||
Connection connection;
|
||||
Random random = new Random();
|
||||
long sid;
|
||||
String server;
|
||||
int port;
|
||||
static Map<String, ICENegociator> negociatorsMap = new HashMap<String, ICENegociator>();
|
||||
//ICENegociator iceNegociator = null;
|
||||
|
||||
public ICEResolver(Connection connection, String server, int port) {
|
||||
super();
|
||||
this.connection = connection;
|
||||
this.server = server;
|
||||
this.port = port;
|
||||
this.setType(Type.ice);
|
||||
}
|
||||
|
||||
public void initialize() throws XMPPException {
|
||||
if (!isResolving() && !isResolved()) {
|
||||
LOGGER.debug("Initialized");
|
||||
|
||||
// Negotiation with a STUN server for a set of interfaces is quite slow, but the results
|
||||
// never change over then instance of a JVM. To increase connection performance considerably
|
||||
// we now cache established/initialized negotiators for each STUN server, so that subsequent uses
|
||||
// of the STUN server are much, much faster.
|
||||
if (negociatorsMap.get(server) == null) {
|
||||
ICENegociator iceNegociator = new ICENegociator(server, port, (short) 1);
|
||||
negociatorsMap.put(server, iceNegociator);
|
||||
|
||||
// gather candidates
|
||||
iceNegociator.gatherCandidateAddresses();
|
||||
// priorize candidates
|
||||
iceNegociator.prioritizeCandidates();
|
||||
}
|
||||
|
||||
}
|
||||
this.setInitialized();
|
||||
}
|
||||
|
||||
public void cancel() throws XMPPException {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the IP and obtain a valid transport method.
|
||||
*/
|
||||
public synchronized void resolve(JingleSession session) throws XMPPException {
|
||||
this.setResolveInit();
|
||||
|
||||
for (TransportCandidate candidate : this.getCandidatesList()) {
|
||||
if (candidate instanceof ICECandidate) {
|
||||
ICECandidate iceCandidate = (ICECandidate) candidate;
|
||||
iceCandidate.removeCandidateEcho();
|
||||
}
|
||||
}
|
||||
|
||||
this.clear();
|
||||
|
||||
// Create a transport candidate for each ICE negotiator candidate we have.
|
||||
ICENegociator iceNegociator = negociatorsMap.get(server);
|
||||
for (Candidate candidate : iceNegociator.getSortedCandidates())
|
||||
try {
|
||||
Candidate.CandidateType type = candidate.getCandidateType();
|
||||
ICECandidate.Type iceType = ICECandidate.Type.local;
|
||||
if (type.equals(Candidate.CandidateType.ServerReflexive))
|
||||
iceType = ICECandidate.Type.srflx;
|
||||
else if (type.equals(Candidate.CandidateType.PeerReflexive))
|
||||
iceType = ICECandidate.Type.prflx;
|
||||
else if (type.equals(Candidate.CandidateType.Relayed))
|
||||
iceType = ICECandidate.Type.relay;
|
||||
else
|
||||
iceType = ICECandidate.Type.host;
|
||||
|
||||
// JBW/GW - 17JUL08: Figure out the zero-based NIC number for this candidate.
|
||||
short nicNum = 0;
|
||||
try {
|
||||
Enumeration<NetworkInterface> nics = NetworkInterface.getNetworkInterfaces();
|
||||
short i = 0;
|
||||
NetworkInterface nic = NetworkInterface.getByInetAddress(candidate.getAddress().getInetAddress());
|
||||
while(nics.hasMoreElements()) {
|
||||
NetworkInterface checkNIC = nics.nextElement();
|
||||
if (checkNIC.equals(nic)) {
|
||||
nicNum = i;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
} catch (SocketException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
TransportCandidate transportCandidate = new ICECandidate(candidate.getAddress().getInetAddress().getHostAddress(), 1, nicNum, String.valueOf(Math.abs(random.nextLong())), candidate.getPort(), "1", candidate.getPriority(), iceType);
|
||||
transportCandidate.setLocalIp(candidate.getBase().getAddress().getInetAddress().getHostAddress());
|
||||
transportCandidate.setPort(getFreePort());
|
||||
try {
|
||||
transportCandidate.addCandidateEcho(session);
|
||||
}
|
||||
catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.addCandidate(transportCandidate);
|
||||
|
||||
LOGGER.debug("Candidate addr: " + candidate.getAddress().getInetAddress() + "|" + candidate.getBase().getAddress().getInetAddress() + " Priority:" + candidate.getPriority());
|
||||
|
||||
}
|
||||
catch (UtilityException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// Get a Relay Candidate from XMPP Server
|
||||
|
||||
if (RTPBridge.serviceAvailable(connection)) {
|
||||
// try {
|
||||
|
||||
String localIp;
|
||||
int network;
|
||||
|
||||
|
||||
// JBW/GW - 17JUL08: ICENegotiator.getPublicCandidate() always returned null in JSTUN 1.7.0, and now the API doesn't exist in JSTUN 1.7.1
|
||||
// if (iceNegociator.getPublicCandidate() != null) {
|
||||
// localIp = iceNegociator.getPublicCandidate().getBase().getAddress().getInetAddress().getHostAddress();
|
||||
// network = iceNegociator.getPublicCandidate().getNetwork();
|
||||
// }
|
||||
// else {
|
||||
{
|
||||
localIp = BridgedResolver.getLocalHost();
|
||||
network = 0;
|
||||
}
|
||||
|
||||
sid = Math.abs(random.nextLong());
|
||||
|
||||
RTPBridge rtpBridge = RTPBridge.getRTPBridge(connection, String.valueOf(sid));
|
||||
|
||||
TransportCandidate localCandidate = new ICECandidate(
|
||||
rtpBridge.getIp(), 1, network, String.valueOf(Math.abs(random.nextLong())), rtpBridge.getPortA(), "1", 0, ICECandidate.Type.relay);
|
||||
localCandidate.setLocalIp(localIp);
|
||||
|
||||
TransportCandidate remoteCandidate = new ICECandidate(
|
||||
rtpBridge.getIp(), 1, network, String.valueOf(Math.abs(random.nextLong())), rtpBridge.getPortB(), "1", 0, ICECandidate.Type.relay);
|
||||
remoteCandidate.setLocalIp(localIp);
|
||||
|
||||
localCandidate.setSymmetric(remoteCandidate);
|
||||
remoteCandidate.setSymmetric(localCandidate);
|
||||
|
||||
localCandidate.setPassword(rtpBridge.getPass());
|
||||
remoteCandidate.setPassword(rtpBridge.getPass());
|
||||
|
||||
localCandidate.setSessionId(rtpBridge.getSid());
|
||||
remoteCandidate.setSessionId(rtpBridge.getSid());
|
||||
|
||||
localCandidate.setConnection(this.connection);
|
||||
remoteCandidate.setConnection(this.connection);
|
||||
|
||||
addCandidate(localCandidate);
|
||||
|
||||
// }
|
||||
// catch (UtilityException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// catch (UnknownHostException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
|
||||
// Get Public Candidate From XMPP Server
|
||||
|
||||
// JBW/GW - 17JUL08 - ICENegotiator.getPublicCandidate() always returned null in JSTUN 1.7.0, and now it doesn't exist in JSTUN 1.7.1
|
||||
// if (iceNegociator.getPublicCandidate() == null) {
|
||||
if (true) {
|
||||
|
||||
String publicIp = RTPBridge.getPublicIP(connection);
|
||||
|
||||
if (publicIp != null && !publicIp.equals("")) {
|
||||
|
||||
Enumeration<NetworkInterface> ifaces = null;
|
||||
|
||||
try {
|
||||
ifaces = NetworkInterface.getNetworkInterfaces();
|
||||
}
|
||||
catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// If detect this address in local machine, don't use it.
|
||||
|
||||
boolean found = false;
|
||||
|
||||
while (ifaces.hasMoreElements() && !false) {
|
||||
|
||||
NetworkInterface iface = ifaces.nextElement();
|
||||
Enumeration<InetAddress> iaddresses = iface.getInetAddresses();
|
||||
|
||||
while (iaddresses.hasMoreElements()) {
|
||||
InetAddress iaddress = iaddresses.nextElement();
|
||||
if (iaddress.getHostAddress().indexOf(publicIp) > -1) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
try {
|
||||
TransportCandidate publicCandidate = new ICECandidate(
|
||||
publicIp, 1, 0, String.valueOf(Math.abs(random.nextLong())), getFreePort(), "1", 0, ICECandidate.Type.srflx);
|
||||
publicCandidate.setLocalIp(InetAddress.getLocalHost().getHostAddress());
|
||||
|
||||
try {
|
||||
publicCandidate.addCandidateEcho(session);
|
||||
}
|
||||
catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
addCandidate(publicCandidate);
|
||||
}
|
||||
catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.setResolveEnd();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,81 +1,81 @@
|
|||
package org.jivesoftware.smackx.jingle.nat;
|
||||
|
||||
import org.jivesoftware.smack.Connection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
import org.jivesoftware.smackx.jingle.listeners.CreatedJingleSessionListener;
|
||||
import org.jivesoftware.smackx.jingle.listeners.JingleSessionListener;
|
||||
import org.jivesoftware.smackx.jingle.media.PayloadType;
|
||||
|
||||
/**
|
||||
* <p/>
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
* <p/>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
public class ICETransportManager extends JingleTransportManager implements JingleSessionListener, CreatedJingleSessionListener {
|
||||
|
||||
ICEResolver iceResolver = null;
|
||||
|
||||
public ICETransportManager(Connection xmppConnection, String server, int port) {
|
||||
iceResolver = new ICEResolver(xmppConnection, server, port);
|
||||
try {
|
||||
iceResolver.initializeAndWait();
|
||||
}
|
||||
catch (XMPPException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
protected TransportResolver createResolver(JingleSession session) {
|
||||
try {
|
||||
iceResolver.resolve(session);
|
||||
}
|
||||
catch (XMPPException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return iceResolver;
|
||||
}
|
||||
|
||||
// Implement a Session Listener to relay candidates after establishment
|
||||
|
||||
public void sessionEstablished(PayloadType pt, TransportCandidate rc, TransportCandidate lc, JingleSession jingleSession) {
|
||||
if (lc instanceof ICECandidate) {
|
||||
if (((ICECandidate) lc).getType().equals("relay")) {
|
||||
RTPBridge rtpBridge = RTPBridge.relaySession(lc.getConnection(), lc.getSessionId(), lc.getPassword(), rc, lc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void sessionDeclined(String reason, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionRedirected(String redirection, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionClosed(String reason, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionClosedOnError(XMPPException e, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionMediaReceived(JingleSession jingleSession, String participant) {
|
||||
// Do Nothing
|
||||
}
|
||||
|
||||
// Session Created
|
||||
|
||||
public void sessionCreated(JingleSession jingleSession) {
|
||||
jingleSession.addListener(this);
|
||||
}
|
||||
}
|
||||
package org.jivesoftware.smackx.jingle.nat;
|
||||
|
||||
import org.jivesoftware.smack.Connection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
import org.jivesoftware.smackx.jingle.listeners.CreatedJingleSessionListener;
|
||||
import org.jivesoftware.smackx.jingle.listeners.JingleSessionListener;
|
||||
import org.jivesoftware.smackx.jingle.media.PayloadType;
|
||||
|
||||
/**
|
||||
* <p/>
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
* <p/>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
public class ICETransportManager extends JingleTransportManager implements JingleSessionListener, CreatedJingleSessionListener {
|
||||
|
||||
ICEResolver iceResolver = null;
|
||||
|
||||
public ICETransportManager(Connection xmppConnection, String server, int port) {
|
||||
iceResolver = new ICEResolver(xmppConnection, server, port);
|
||||
try {
|
||||
iceResolver.initializeAndWait();
|
||||
}
|
||||
catch (XMPPException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
protected TransportResolver createResolver(JingleSession session) {
|
||||
try {
|
||||
iceResolver.resolve(session);
|
||||
}
|
||||
catch (XMPPException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return iceResolver;
|
||||
}
|
||||
|
||||
// Implement a Session Listener to relay candidates after establishment
|
||||
|
||||
public void sessionEstablished(PayloadType pt, TransportCandidate rc, TransportCandidate lc, JingleSession jingleSession) {
|
||||
if (lc instanceof ICECandidate) {
|
||||
if (((ICECandidate) lc).getType().equals("relay")) {
|
||||
RTPBridge rtpBridge = RTPBridge.relaySession(lc.getConnection(), lc.getSessionId(), lc.getPassword(), rc, lc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void sessionDeclined(String reason, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionRedirected(String redirection, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionClosed(String reason, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionClosedOnError(XMPPException e, JingleSession jingleSession) {
|
||||
}
|
||||
|
||||
public void sessionMediaReceived(JingleSession jingleSession, String participant) {
|
||||
// Do Nothing
|
||||
}
|
||||
|
||||
// Session Created
|
||||
|
||||
public void sessionCreated(JingleSession jingleSession) {
|
||||
jingleSession.addListener(this);
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,29 +1,29 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2003-2005 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jivesoftware.smackx.jingle.nat;
|
||||
|
||||
/**
|
||||
* Listener for ECHO Test Results
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public interface ResultListener {
|
||||
|
||||
public void testFinished(TestResult result, TransportCandidate candidate);
|
||||
|
||||
}
|
||||
/**
|
||||
*
|
||||
* Copyright 2003-2005 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jivesoftware.smackx.jingle.nat;
|
||||
|
||||
/**
|
||||
* Listener for ECHO Test Results
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public interface ResultListener {
|
||||
|
||||
public void testFinished(TestResult result, TransportCandidate candidate);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,284 +1,284 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.nat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smack.PacketCollector;
|
||||
import org.jivesoftware.smack.SmackConfiguration;
|
||||
import org.jivesoftware.smack.Connection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smack.filter.PacketIDFilter;
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smack.provider.IQProvider;
|
||||
import org.jivesoftware.smack.provider.ProviderManager;
|
||||
import org.jivesoftware.smackx.ServiceDiscoveryManager;
|
||||
import org.jivesoftware.smackx.jingle.SmackLogger;
|
||||
import org.jivesoftware.smackx.packet.DiscoverInfo;
|
||||
import org.jivesoftware.smackx.packet.DiscoverItems;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
/**
|
||||
* STUN IQ Packet used to request and retrieve a STUN server and port to make p2p connections easier. STUN is usually used by Jingle Media Transmission between two parties that are behind NAT.
|
||||
* <p/>
|
||||
* High Level Usage Example:
|
||||
* <p/>
|
||||
* STUN stun = STUN.getSTUNServer(connection);
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public class STUN extends IQ {
|
||||
|
||||
private static final SmackLogger LOGGER = SmackLogger.getLogger(STUN.class);
|
||||
|
||||
private List<StunServerAddress> servers = new ArrayList<StunServerAddress>();
|
||||
|
||||
private String publicIp = null;
|
||||
|
||||
/**
|
||||
* Element name of the packet extension.
|
||||
*/
|
||||
public static final String DOMAIN = "stun";
|
||||
|
||||
/**
|
||||
* Element name of the packet extension.
|
||||
*/
|
||||
public static final String ELEMENT_NAME = "query";
|
||||
|
||||
/**
|
||||
* Namespace of the packet extension.
|
||||
*/
|
||||
public static final String NAMESPACE = "google:jingleinfo";
|
||||
|
||||
static {
|
||||
ProviderManager.getInstance().addIQProvider(ELEMENT_NAME, NAMESPACE, new STUN.Provider());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a STUN IQ
|
||||
*/
|
||||
public STUN() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of STUN Servers recommended by the Server
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<StunServerAddress> getServers() {
|
||||
return servers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Public Ip returned from the XMPP server
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getPublicIp() {
|
||||
return publicIp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Public Ip returned from the XMPP server
|
||||
*
|
||||
* @param publicIp
|
||||
*/
|
||||
private void setPublicIp(String publicIp) {
|
||||
this.publicIp = publicIp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Child Element XML of the Packet
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getChildElementXML() {
|
||||
StringBuilder str = new StringBuilder();
|
||||
str.append("<" + ELEMENT_NAME + " xmlns='" + NAMESPACE + "'/>");
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* IQProvider for RTP Bridge packets.
|
||||
* Parse receive RTPBridge packet to a RTPBridge instance
|
||||
*
|
||||
* @author Thiago Rocha
|
||||
*/
|
||||
public static class Provider implements IQProvider {
|
||||
|
||||
public Provider() {
|
||||
super();
|
||||
}
|
||||
|
||||
public IQ parseIQ(XmlPullParser parser) throws Exception {
|
||||
|
||||
boolean done = false;
|
||||
|
||||
int eventType;
|
||||
String elementName;
|
||||
String namespace;
|
||||
|
||||
if (!parser.getNamespace().equals(NAMESPACE))
|
||||
throw new Exception("Not a STUN packet");
|
||||
|
||||
STUN iq = new STUN();
|
||||
|
||||
// Start processing sub-elements
|
||||
while (!done) {
|
||||
eventType = parser.next();
|
||||
elementName = parser.getName();
|
||||
namespace = parser.getNamespace();
|
||||
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
if (elementName.equals("server")) {
|
||||
String host = null;
|
||||
String port = null;
|
||||
for (int i = 0; i < parser.getAttributeCount(); i++) {
|
||||
if (parser.getAttributeName(i).equals("host"))
|
||||
host = parser.getAttributeValue(i);
|
||||
else if (parser.getAttributeName(i).equals("udp"))
|
||||
port = parser.getAttributeValue(i);
|
||||
}
|
||||
if (host != null && port != null)
|
||||
iq.servers.add(new StunServerAddress(host, port));
|
||||
}
|
||||
else if (elementName.equals("publicip")) {
|
||||
String host = null;
|
||||
for (int i = 0; i < parser.getAttributeCount(); i++) {
|
||||
if (parser.getAttributeName(i).equals("ip"))
|
||||
host = parser.getAttributeValue(i);
|
||||
}
|
||||
if (host != null && !host.equals(""))
|
||||
iq.setPublicIp(host);
|
||||
}
|
||||
}
|
||||
else if (eventType == XmlPullParser.END_TAG) {
|
||||
if (parser.getName().equals(ELEMENT_NAME)) {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return iq;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new STUN Server Address and port from the server.
|
||||
* If a error occurs or the server don't support STUN Service, null is returned.
|
||||
*
|
||||
* @param connection
|
||||
* @return
|
||||
*/
|
||||
public static STUN getSTUNServer(Connection connection) {
|
||||
|
||||
if (!connection.isConnected()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
STUN stunPacket = new STUN();
|
||||
stunPacket.setTo(DOMAIN + "." + connection.getServiceName());
|
||||
|
||||
PacketCollector collector = connection
|
||||
.createPacketCollector(new PacketIDFilter(stunPacket.getPacketID()));
|
||||
|
||||
connection.sendPacket(stunPacket);
|
||||
|
||||
STUN response = (STUN) collector
|
||||
.nextResult(SmackConfiguration.getPacketReplyTimeout());
|
||||
|
||||
// Cancel the collector.
|
||||
collector.cancel();
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the server support STUN Service.
|
||||
*
|
||||
* @param xmppConnection
|
||||
* @return
|
||||
*/
|
||||
public static boolean serviceAvailable(Connection connection) {
|
||||
|
||||
if (!connection.isConnected()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LOGGER.debug("Service listing");
|
||||
|
||||
ServiceDiscoveryManager disco = ServiceDiscoveryManager
|
||||
.getInstanceFor(connection);
|
||||
try {
|
||||
DiscoverItems items = disco.discoverItems(connection.getServiceName());
|
||||
|
||||
Iterator<DiscoverItems.Item> iter = items.getItems();
|
||||
while (iter.hasNext()) {
|
||||
DiscoverItems.Item item = iter.next();
|
||||
DiscoverInfo info = disco.discoverInfo(item.getEntityID());
|
||||
|
||||
Iterator<DiscoverInfo.Identity> iter2 = info.getIdentities();
|
||||
while (iter2.hasNext()) {
|
||||
DiscoverInfo.Identity identity = iter2.next();
|
||||
if (identity.getCategory().equals("proxy") && identity.getType().equals("stun"))
|
||||
if (info.containsFeature(NAMESPACE))
|
||||
return true;
|
||||
}
|
||||
|
||||
LOGGER.debug(item.getName()+"-"+info.getType());
|
||||
|
||||
}
|
||||
}
|
||||
catch (XMPPException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides easy abstract to store STUN Server Addresses and Ports
|
||||
*/
|
||||
public static class StunServerAddress {
|
||||
|
||||
private String server;
|
||||
private String port;
|
||||
|
||||
public StunServerAddress(String server, String port) {
|
||||
this.server = server;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Host Address
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Server Port
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getPort() {
|
||||
return port;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.nat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smack.PacketCollector;
|
||||
import org.jivesoftware.smack.SmackConfiguration;
|
||||
import org.jivesoftware.smack.Connection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smack.filter.PacketIDFilter;
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smack.provider.IQProvider;
|
||||
import org.jivesoftware.smack.provider.ProviderManager;
|
||||
import org.jivesoftware.smackx.ServiceDiscoveryManager;
|
||||
import org.jivesoftware.smackx.jingle.SmackLogger;
|
||||
import org.jivesoftware.smackx.packet.DiscoverInfo;
|
||||
import org.jivesoftware.smackx.packet.DiscoverItems;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
/**
|
||||
* STUN IQ Packet used to request and retrieve a STUN server and port to make p2p connections easier. STUN is usually used by Jingle Media Transmission between two parties that are behind NAT.
|
||||
* <p/>
|
||||
* High Level Usage Example:
|
||||
* <p/>
|
||||
* STUN stun = STUN.getSTUNServer(connection);
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public class STUN extends IQ {
|
||||
|
||||
private static final SmackLogger LOGGER = SmackLogger.getLogger(STUN.class);
|
||||
|
||||
private List<StunServerAddress> servers = new ArrayList<StunServerAddress>();
|
||||
|
||||
private String publicIp = null;
|
||||
|
||||
/**
|
||||
* Element name of the packet extension.
|
||||
*/
|
||||
public static final String DOMAIN = "stun";
|
||||
|
||||
/**
|
||||
* Element name of the packet extension.
|
||||
*/
|
||||
public static final String ELEMENT_NAME = "query";
|
||||
|
||||
/**
|
||||
* Namespace of the packet extension.
|
||||
*/
|
||||
public static final String NAMESPACE = "google:jingleinfo";
|
||||
|
||||
static {
|
||||
ProviderManager.getInstance().addIQProvider(ELEMENT_NAME, NAMESPACE, new STUN.Provider());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a STUN IQ
|
||||
*/
|
||||
public STUN() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of STUN Servers recommended by the Server
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<StunServerAddress> getServers() {
|
||||
return servers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Public Ip returned from the XMPP server
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getPublicIp() {
|
||||
return publicIp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Public Ip returned from the XMPP server
|
||||
*
|
||||
* @param publicIp
|
||||
*/
|
||||
private void setPublicIp(String publicIp) {
|
||||
this.publicIp = publicIp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Child Element XML of the Packet
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getChildElementXML() {
|
||||
StringBuilder str = new StringBuilder();
|
||||
str.append("<" + ELEMENT_NAME + " xmlns='" + NAMESPACE + "'/>");
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* IQProvider for RTP Bridge packets.
|
||||
* Parse receive RTPBridge packet to a RTPBridge instance
|
||||
*
|
||||
* @author Thiago Rocha
|
||||
*/
|
||||
public static class Provider implements IQProvider {
|
||||
|
||||
public Provider() {
|
||||
super();
|
||||
}
|
||||
|
||||
public IQ parseIQ(XmlPullParser parser) throws Exception {
|
||||
|
||||
boolean done = false;
|
||||
|
||||
int eventType;
|
||||
String elementName;
|
||||
String namespace;
|
||||
|
||||
if (!parser.getNamespace().equals(NAMESPACE))
|
||||
throw new Exception("Not a STUN packet");
|
||||
|
||||
STUN iq = new STUN();
|
||||
|
||||
// Start processing sub-elements
|
||||
while (!done) {
|
||||
eventType = parser.next();
|
||||
elementName = parser.getName();
|
||||
namespace = parser.getNamespace();
|
||||
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
if (elementName.equals("server")) {
|
||||
String host = null;
|
||||
String port = null;
|
||||
for (int i = 0; i < parser.getAttributeCount(); i++) {
|
||||
if (parser.getAttributeName(i).equals("host"))
|
||||
host = parser.getAttributeValue(i);
|
||||
else if (parser.getAttributeName(i).equals("udp"))
|
||||
port = parser.getAttributeValue(i);
|
||||
}
|
||||
if (host != null && port != null)
|
||||
iq.servers.add(new StunServerAddress(host, port));
|
||||
}
|
||||
else if (elementName.equals("publicip")) {
|
||||
String host = null;
|
||||
for (int i = 0; i < parser.getAttributeCount(); i++) {
|
||||
if (parser.getAttributeName(i).equals("ip"))
|
||||
host = parser.getAttributeValue(i);
|
||||
}
|
||||
if (host != null && !host.equals(""))
|
||||
iq.setPublicIp(host);
|
||||
}
|
||||
}
|
||||
else if (eventType == XmlPullParser.END_TAG) {
|
||||
if (parser.getName().equals(ELEMENT_NAME)) {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return iq;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new STUN Server Address and port from the server.
|
||||
* If a error occurs or the server don't support STUN Service, null is returned.
|
||||
*
|
||||
* @param connection
|
||||
* @return
|
||||
*/
|
||||
public static STUN getSTUNServer(Connection connection) {
|
||||
|
||||
if (!connection.isConnected()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
STUN stunPacket = new STUN();
|
||||
stunPacket.setTo(DOMAIN + "." + connection.getServiceName());
|
||||
|
||||
PacketCollector collector = connection
|
||||
.createPacketCollector(new PacketIDFilter(stunPacket.getPacketID()));
|
||||
|
||||
connection.sendPacket(stunPacket);
|
||||
|
||||
STUN response = (STUN) collector
|
||||
.nextResult(SmackConfiguration.getPacketReplyTimeout());
|
||||
|
||||
// Cancel the collector.
|
||||
collector.cancel();
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the server support STUN Service.
|
||||
*
|
||||
* @param xmppConnection
|
||||
* @return
|
||||
*/
|
||||
public static boolean serviceAvailable(Connection connection) {
|
||||
|
||||
if (!connection.isConnected()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LOGGER.debug("Service listing");
|
||||
|
||||
ServiceDiscoveryManager disco = ServiceDiscoveryManager
|
||||
.getInstanceFor(connection);
|
||||
try {
|
||||
DiscoverItems items = disco.discoverItems(connection.getServiceName());
|
||||
|
||||
Iterator<DiscoverItems.Item> iter = items.getItems();
|
||||
while (iter.hasNext()) {
|
||||
DiscoverItems.Item item = iter.next();
|
||||
DiscoverInfo info = disco.discoverInfo(item.getEntityID());
|
||||
|
||||
Iterator<DiscoverInfo.Identity> iter2 = info.getIdentities();
|
||||
while (iter2.hasNext()) {
|
||||
DiscoverInfo.Identity identity = iter2.next();
|
||||
if (identity.getCategory().equals("proxy") && identity.getType().equals("stun"))
|
||||
if (info.containsFeature(NAMESPACE))
|
||||
return true;
|
||||
}
|
||||
|
||||
LOGGER.debug(item.getName()+"-"+info.getType());
|
||||
|
||||
}
|
||||
}
|
||||
catch (XMPPException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides easy abstract to store STUN Server Addresses and Ports
|
||||
*/
|
||||
public static class StunServerAddress {
|
||||
|
||||
private String server;
|
||||
private String port;
|
||||
|
||||
public StunServerAddress(String server, String port) {
|
||||
this.server = server;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Host Address
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Server Port
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getPort() {
|
||||
return port;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,48 +1,48 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.nat;
|
||||
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
|
||||
/**
|
||||
* A Jingle Transport Manager implementation to be used on NAT networks with STUN Service NOT Blocked.
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public class STUNTransportManager extends JingleTransportManager {
|
||||
STUNResolver stunResolver = null;
|
||||
|
||||
public STUNTransportManager() {
|
||||
stunResolver = new STUNResolver() {
|
||||
};
|
||||
try {
|
||||
stunResolver.initializeAndWait();
|
||||
} catch (XMPPException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
protected TransportResolver createResolver(JingleSession session) {
|
||||
try {
|
||||
stunResolver.resolve(session);
|
||||
} catch (XMPPException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return stunResolver;
|
||||
}
|
||||
}
|
||||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.nat;
|
||||
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smackx.jingle.JingleSession;
|
||||
|
||||
/**
|
||||
* A Jingle Transport Manager implementation to be used on NAT networks with STUN Service NOT Blocked.
|
||||
*
|
||||
* @author Thiago Camargo
|
||||
*/
|
||||
public class STUNTransportManager extends JingleTransportManager {
|
||||
STUNResolver stunResolver = null;
|
||||
|
||||
public STUNTransportManager() {
|
||||
stunResolver = new STUNResolver() {
|
||||
};
|
||||
try {
|
||||
stunResolver.initializeAndWait();
|
||||
} catch (XMPPException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
protected TransportResolver createResolver(JingleSession session) {
|
||||
try {
|
||||
stunResolver.resolve(session);
|
||||
} catch (XMPPException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return stunResolver;
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -12,108 +12,108 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle.nat;
|
||||
|
||||
import org.jivesoftware.smack.test.SmackTestCase;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
public class BridgedResolverTest extends SmackTestCase {
|
||||
|
||||
private int counter;
|
||||
|
||||
private final Object mutex = new Object();
|
||||
|
||||
public BridgedResolverTest(String arg) {
|
||||
super(arg);
|
||||
}
|
||||
|
||||
// Counter management
|
||||
|
||||
private void resetCounter() {
|
||||
synchronized (mutex) {
|
||||
counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void incCounter() {
|
||||
synchronized (mutex) {
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
private int valCounter() {
|
||||
int val;
|
||||
synchronized (mutex) {
|
||||
val = counter;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
public void testCheckService() {
|
||||
assertTrue(RTPBridge.serviceAvailable(getConnection(0)));
|
||||
}
|
||||
|
||||
public void testGetBridge() {
|
||||
|
||||
resetCounter();
|
||||
|
||||
RTPBridge rtpBridge = RTPBridge.getRTPBridge(getConnection(0), "001");
|
||||
|
||||
System.out.println(rtpBridge.getIp() + " portA:" + rtpBridge.getPortA() + " portB:" + rtpBridge.getPortB());
|
||||
|
||||
if (rtpBridge != null) {
|
||||
if (rtpBridge.getIp() != null) incCounter();
|
||||
if (rtpBridge.getPortA() != -1) incCounter();
|
||||
if (rtpBridge.getPortB() != -1) incCounter();
|
||||
}
|
||||
|
||||
assertTrue(valCounter() == 3);
|
||||
}
|
||||
|
||||
public void testGetPublicIp() {
|
||||
|
||||
resetCounter();
|
||||
|
||||
String publicIp = RTPBridge.getPublicIP(getConnection(0));
|
||||
|
||||
System.out.println(publicIp);
|
||||
|
||||
if (publicIp != null) {
|
||||
incCounter();
|
||||
}
|
||||
|
||||
try {
|
||||
InetAddress localaddr = InetAddress.getLocalHost();
|
||||
System.out.println("main Local IP Address : " + localaddr.getHostAddress());
|
||||
System.out.println("main Local hostname : " + localaddr.getHostName());
|
||||
|
||||
InetAddress[] localaddrs = InetAddress.getAllByName("localhost");
|
||||
for (int i = 0; i < localaddrs.length; i++) {
|
||||
if (!localaddrs[i].equals(localaddr)) {
|
||||
System.out.println("alt Local IP Address : " + localaddrs[i].getHostAddress());
|
||||
System.out.println("alt Local hostname : " + localaddrs[i].getHostName());
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (UnknownHostException e) {
|
||||
System.err.println("Can't detect localhost : " + e);
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
assertTrue(valCounter() == 1);
|
||||
}
|
||||
|
||||
protected int getMaxConnections() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
package org.jivesoftware.smackx.jingle.nat;
|
||||
|
||||
import org.jivesoftware.smack.test.SmackTestCase;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
public class BridgedResolverTest extends SmackTestCase {
|
||||
|
||||
private int counter;
|
||||
|
||||
private final Object mutex = new Object();
|
||||
|
||||
public BridgedResolverTest(String arg) {
|
||||
super(arg);
|
||||
}
|
||||
|
||||
// Counter management
|
||||
|
||||
private void resetCounter() {
|
||||
synchronized (mutex) {
|
||||
counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void incCounter() {
|
||||
synchronized (mutex) {
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
private int valCounter() {
|
||||
int val;
|
||||
synchronized (mutex) {
|
||||
val = counter;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
public void testCheckService() {
|
||||
assertTrue(RTPBridge.serviceAvailable(getConnection(0)));
|
||||
}
|
||||
|
||||
public void testGetBridge() {
|
||||
|
||||
resetCounter();
|
||||
|
||||
RTPBridge rtpBridge = RTPBridge.getRTPBridge(getConnection(0), "001");
|
||||
|
||||
System.out.println(rtpBridge.getIp() + " portA:" + rtpBridge.getPortA() + " portB:" + rtpBridge.getPortB());
|
||||
|
||||
if (rtpBridge != null) {
|
||||
if (rtpBridge.getIp() != null) incCounter();
|
||||
if (rtpBridge.getPortA() != -1) incCounter();
|
||||
if (rtpBridge.getPortB() != -1) incCounter();
|
||||
}
|
||||
|
||||
assertTrue(valCounter() == 3);
|
||||
}
|
||||
|
||||
public void testGetPublicIp() {
|
||||
|
||||
resetCounter();
|
||||
|
||||
String publicIp = RTPBridge.getPublicIP(getConnection(0));
|
||||
|
||||
System.out.println(publicIp);
|
||||
|
||||
if (publicIp != null) {
|
||||
incCounter();
|
||||
}
|
||||
|
||||
try {
|
||||
InetAddress localaddr = InetAddress.getLocalHost();
|
||||
System.out.println("main Local IP Address : " + localaddr.getHostAddress());
|
||||
System.out.println("main Local hostname : " + localaddr.getHostName());
|
||||
|
||||
InetAddress[] localaddrs = InetAddress.getAllByName("localhost");
|
||||
for (int i = 0; i < localaddrs.length; i++) {
|
||||
if (!localaddrs[i].equals(localaddr)) {
|
||||
System.out.println("alt Local IP Address : " + localaddrs[i].getHostAddress());
|
||||
System.out.println("alt Local hostname : " + localaddrs[i].getHostName());
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (UnknownHostException e) {
|
||||
System.err.println("Can't detect localhost : " + e);
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
assertTrue(valCounter() == 1);
|
||||
}
|
||||
|
||||
protected int getMaxConnections() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- Default configuration for Smack test cases. -->
|
||||
<testcase>
|
||||
|
||||
<!-- Host and port of the XMPP server to use -->
|
||||
<host>localhost</host>
|
||||
<port>5222</port>
|
||||
|
||||
<!-- Chat and MUC domain names to use -->
|
||||
<chat>chat</chat>
|
||||
<muc>conference</muc>
|
||||
|
||||
<?xml version="1.0"?>
|
||||
<!-- Default configuration for Smack test cases. -->
|
||||
<testcase>
|
||||
|
||||
<!-- Host and port of the XMPP server to use -->
|
||||
<host>localhost</host>
|
||||
<port>5222</port>
|
||||
|
||||
<!-- Chat and MUC domain names to use -->
|
||||
<chat>chat</chat>
|
||||
<muc>conference</muc>
|
||||
|
||||
</testcase>
|
Loading…
Add table
Add a link
Reference in a new issue