Commit b58ba7b6 by amir

first version

parent d5b8b688
Pipeline #93 skipped in 0 seconds
Showing with 4892 additions and 0 deletions
/build/
/bin/
.gradle
.settings
.idea
.lck
.project
.classpath
gradle/
group 'com.ipgallery.common'
version '1.0.0'
apply plugin: 'java'
apply plugin: 'maven-publish'
sourceCompatibility = 1.8
repositories {
mavenCentral()
maven { url "http://172.16.1.132:8081/repository/internal" }
maven { url "http://mandubian-mvn.googlecode.com/svn/trunk/mandubian-mvn/repository" }
}
dependencies {
//compile 'javax.servlet:sip-api:1.0'
testCompile group: 'junit', name: 'junit', version: '4.11'
}
publishing {
publications {
repositories.maven {
url 'http://172.16.1.132:8081/repository/internal'
credentials {
username "admin"
password "giptmgr1"
}
}
mavenJava(MavenPublication) {
//artifactId 'group-service'
from components.java
}
}
}
\ No newline at end of file
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
rootProject.name = 'rcs-core-api'
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core;
import java.util.logging.Logger;
import utils.PhoneUtils;
/**
* Core (singleton pattern)
*
* @author JM. Auffret
*/
public class Core {
/**
* Singleton instance
*/
private static Core instance = null;
/**
* Core listener
*/
private CoreListener listener;
/**
* Core status
*/
private boolean started = false;
/**
* IMS module
*/
// private ImsModule imsModule;
/**
* Sip Factory
*/
//SipFactory sipFactory = null;
/**
* Address book manager
*/
// private AddressBookManager addressBookManager;
/**
* The logger
*/
private Logger logger = Logger.getLogger(this.getClass().getName());
/**
* Returns the singleton instance
*
* @return Core instance
*/
public static Core getInstance() {
return instance;
}
/**
* Instanciate the core
*
* @param listener Listener
* @return Core instance
* @throws CoreException
*/
public synchronized static Core createCore(CoreListener listener) throws CoreException {
if (instance == null) {
instance = new Core(listener);
}
return instance;
}
/**
* Terminate the core
*/
public synchronized static void terminateCore() {
if (instance != null) {
instance.stopCore();
}
instance = null;
}
/**
* Constructor
*
* @param listener Listener
* @throws CoreException
*/
private Core(CoreListener listener) throws CoreException {
logger.info("Terminal core initialization");
// Set core event listener
this.listener = listener;
//this.sipFactory = sf;
// Get UUID
// logger.info("My device UUID is " + DeviceUtils.getDeviceUUID(AndroidFactory.getApplicationContext()));
// Initialize the phone utils
PhoneUtils.initialize(/*AndroidFactory.getApplicationContext()*/);
// Get country code
logger.info("My country code is " + PhoneUtils.getCountryCode());
// Create the address book manager
//addressBookManager = new AddressBookManager();
// Create the IMS module
// imsModule = new ImsModule(this);
logger.info("Terminal core is created with success");
}
/**
* Returns the event listener
*
* @return Listener
*/
public CoreListener getListener() {
return listener;
}
/**
* Returns the IMS module
*
* @return IMS module
*/
// public ImsModule getImsModule() {
// return imsModule;
// }
/**
* Returns the address book manager
*/
// public AddressBookManager getAddressBookManager(){
// return addressBookManager;
// }
/**
* Is core started
*
* @return Boolean
*/
public boolean isCoreStarted() {
return started;
}
/**
* Start the terminal core
*
* @throws CoreException
*/
public synchronized void startCore() throws CoreException {
if (started) {
// Already started
return;
}
// Start the IMS module
// imsModule.start();
// Start the address book monitoring
//addressBookManager.startAddressBookMonitoring();
// Notify event listener
listener.handleCoreLayerStarted();
started = true;
logger.info("RCS core service has been started with success");
}
/**
* Stop the terminal core
*/
public synchronized void stopCore() {
if (!started) {
// Already stopped
return;
}
logger.info("Stop the RCS core service");
// Stop the address book monitoring
//addressBookManager.stopAddressBookMonitoring();
try {
// Stop the IMS module
// imsModule.stop();
} catch(Exception e) {
logger.severe("Error during core shutdown: " + e);
}
// Notify event listener
listener.handleCoreLayerStopped();
started = false;
logger.info("RCS core service has been stopped with success");
}
/**
* Returns the terms service
*
* @return Terms service
*/
// public TermsConditionsService getTermsConditionsService() {
// return getImsModule().getTermsConditionsService();
// }
/**
* Returns the presence service
*
* @return Presence service
*/
// public PresenceService getPresenceService() {
// return getImsModule().getPresenceService();
// }
/**
* Returns the capabity service
*
* @return Capability service
*/
// public CapabilityService getCapabilityService() {
// return getImsModule().getCapabilityService();
// }
/**
* Returns the richcall service
*
* @return Rich call service
*/
// public RichcallService getRichcallService() {
// return getImsModule().getRichcallService();
// }
/**
* Returns the IM service
*
* @return IM service
*/
// public InstantMessagingService getImService() {
// return getImsModule().getInstantMessagingService();
// }
/**
* Returns the SIP service
*
* @return SIP service
*/
// public SipService getSipService() {
// return getImsModule().getSipService();
// }
// public SipFactory getSipFactory() {
// return sipFactory;
// }
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core;
/**
* Core module exception
*
* @author JM. Auffret
*/
public class CoreException extends java.lang.Exception {
static final long serialVersionUID = 1L;
/**
* Constructor
*
* @param error Error message
*/
public CoreException(String error) {
super(error);
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core;
/**
* Observer of core events
*
* @author JM. Auffret
*/
public interface CoreListener {
/**
* Core layer has been started
*/
public void handleCoreLayerStarted();
/**
* Core layer has been stopped
*/
public void handleCoreLayerStopped();
/**
* Registered to IMS
*/
public void handleRegistrationSuccessful();
/**
* IMS registration has failed
*
* @param error Error
*/
// public void handleRegistrationFailed(ImsError error);
/**
* Unregistered from IMS
*/
// public void handleRegistrationTerminated();
/**
* A new presence sharing notification has been received
*
* @param contact Contact
* @param status Status
* @param reason Reason
*/
public void handlePresenceSharingNotification(String contact, String status, String reason);
/**
* A new presence info notification has been received
*
* @param contact Contact
* @param presense Presence info document
*/
// public void handlePresenceInfoNotification(String contact, PidfDocument presence);
/**
* Capabilities update notification has been received
*
* @param contact Contact
* @param capabilities Capabilities
*/
//public void handleCapabilitiesNotification(String contact, Capabilities capabilities);
/**
* A new presence sharing invitation has been received
*
* @param contact Contact
*/
public void handlePresenceSharingInvitation(String contact);
/**
* A new content sharing transfer invitation has been received
*
* @param session CSh session
*/
// public void handleContentSharingTransferInvitation(ImageTransferSession session);
/**
* A new content sharing streaming invitation has been received
*
* @param session CSh session
*/
// public void handleContentSharingStreamingInvitation(VideoStreamingSession session);
/**
* A new file transfer invitation has been received
*
* @param session File transfer session
*/
// public void handleFileTransferInvitation(FileSharingSession session);
/**
* New one-to-one chat session invitation
*
* @param session Chat session
*/
//public void handleOneOneChatSessionInvitation(TerminatingOne2OneChatSession session);
/**
* New ad-hoc group chat session invitation
*
* @param session Chat session
*/
//public void handleAdhocGroupChatSessionInvitation(TerminatingAdhocGroupChatSession session);
/**
* One-to-one chat session extended to a group chat session
*
* @param groupSession Group chat session
* @param oneoneSession 1-1 chat session
*/
// public void handleOneOneChatSessionExtended(GroupChatSession groupSession, OneOneChatSession oneoneSession);
/**
* Store and Forward messages session invitation
*
* @param session Chat session
*/
// public void handleStoreAndForwardMsgSessionInvitation(TerminatingStoreAndForwardMsgSession session);
/**
* New message delivery status
*
* @param contact Contact
* @param msgId Message ID
* @param status Delivery status
*/
public void handleMessageDeliveryStatus(String contact, String msgId, String status,int handleThread);
/**
* New SIP session invitation
*
* @param session SIP session
*/
// public void handleSipSessionInvitation(TerminatingSipSession session);
/**
* User terms confirmation request
*
* @param remote Remote server
* @param id Request ID
* @param type Type of request
* @param pin PIN number requested
* @param subject Subject
* @param text Text
*/
public void handleUserConfirmationRequest(String remote, String id, String type, boolean pin, String subject, String text);
/**
* User terms confirmation acknowledge
*
* @param remote Remote server
* @param id Request ID
* @param status Status
* @param subject Subject
* @param text Text
*/
public void handleUserConfirmationAck(String remote, String id, String status, String subject, String text);
/**
* SIM has changed
*/
//public void handleSimHasChanged();
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.content;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Vector;
import core.ims.network.sip.SipUtils;
import core.ims.protocol.sdp.MediaAttribute;
import core.ims.protocol.sdp.MediaDescription;
import core.ims.protocol.sdp.SdpParser;
import platform.file.FileFactory;
import utils.MimeManager;
/**
* Multimedia content manager
*
* @author amir aharon
*/
public class ContentManager{
/**
* Generate an URL for the received content
*
* @param filename Filename
* @param mime MIME type
* @return URL
*/
public static String generateUrlForReceivedContent(String filename, String mime) {
// Generate a file path
String path;
if (mime.startsWith("image")) {
path = FileFactory.getFactory().getPhotoRootDirectory();
} else
if (mime.startsWith("video")) {
path = FileFactory.getFactory().getVideoRootDirectory();
} else {
path = FileFactory.getFactory().getFileRootDirectory();
}
// Check that the filename will not overwrite existing file
// We modify it if a file of the same name exists, by appending _1 before the extension
// For example if image.jpeg exists, next file will be image_1.jpeg, then image_2.jpeg etc
String extension = "";
if ((filename!=null) && (filename.indexOf('.')!=-1)){
// if extension is present, split it
extension = "." + filename.substring(filename.lastIndexOf('.')+1);
filename = filename.substring(0, filename.lastIndexOf('.'));
}
String destination = filename;
int i = 1;
while(FileFactory.getFactory().fileExists(path + destination + extension)){
destination = filename + '_' + i;
i++;
}
// Return free destination url
return path + destination + extension;
}
/**
* Save a content in the local directory of the device
*
* @param content Content to be saved
* @throws IOException
*/
public static void saveContent(MmContent content) throws IOException {
// Write data
OutputStream os = FileFactory.getFactory().openFileOutputStream(content.getUrl());
os.write(content.getData());
os.flush();
os.close();
// Update the media storage
FileFactory.getFactory().updateMediaStorage(content.getUrl());
}
/**
* Create a content object from URL description
*
* @param url Content URL
* @param size Content size
* @return Content instance
*/
public static MmContent createMmContentFromUrl(String url, long size) {
String ext = MimeManager.getFileExtension(url);
String mime = MimeManager.getMimeType(ext);
if (mime != null) {
if (mime.startsWith("image/")) {
return new PhotoContent(url, mime, size);
}
if (mime.startsWith("video/")) {
return new VideoContent(url, mime, size);
}
}
return new FileContent(url, size);
}
/**
* Create a content object from MIME type
*
* @param url Content URL
* @param mime MIME type
* @param size Content size
* @return Content instance
*/
public static MmContent createMmContentFromMime(String url, String mime, long size) {
if (mime.startsWith("image/")) {
// Photo content
return new PhotoContent(url, mime, size);
}
if (mime.startsWith("video/")) {
// Video content
return new VideoContent(url, mime, size);
}
if (mime.startsWith("application/")) {
// File content
return new FileContent(url, size);
}
return null;
}
/**
* Create a live video content object
*
* @param codec Codec
* @return Content instance
*/
public static LiveVideoContent createLiveVideoContent(String codec) {
return new LiveVideoContent("video/"+codec);
}
/**
* Create a generic live video content object
*
* @return Content instance
*/
public static LiveVideoContent createGenericLiveVideoContent() {
return new LiveVideoContent("video/*");
}
/**
* Create a live video content object
*
* @param sdp SDP part
* @return Content instance
*/
public static LiveVideoContent createLiveVideoContentFromSdp(byte[] sdp) {
// Parse the remote SDP part
SdpParser parser = new SdpParser(sdp);
Vector<MediaDescription> media = parser.getMediaDescriptions();
MediaDescription desc = media.elementAt(0);
String rtpmap = desc.getMediaAttribute("rtpmap").getValue();
// Extract the video encoding
String encoding = rtpmap.substring(rtpmap.indexOf(desc.payload)+desc.payload.length()+1);
String codec = encoding.toLowerCase().trim();
int index = encoding.indexOf("/");
if (index != -1) {
codec = encoding.substring(0, index);
}
return createLiveVideoContent(codec);
}
/**
* Create a content object from SDP data
*
* @param sdp SDP part
* @return Content instance
*/
public static MmContent createMmContentFromSdp(String sdp) {
// Set the content
try {
SdpParser parser = new SdpParser(sdp.getBytes());
Vector<MediaDescription> media = parser.getMediaDescriptions();
MediaDescription desc = media.elementAt(0);
MediaAttribute attr1 = desc.getMediaAttribute("file-selector");
String fileSelectorValue = attr1.getValue();
String mime = SipUtils.extractParameter(fileSelectorValue, "type:", "application/octet-stream");
long size = Long.parseLong(SipUtils.extractParameter(fileSelectorValue, "size:", "-1"));
String filename = SipUtils.extractParameter(fileSelectorValue, "name:", "");
String url = ContentManager.generateUrlForReceivedContent(filename, mime);
MmContent content = ContentManager.createMmContentFromMime(url, mime, size);
return content;
} catch(Exception e) {
return null;
}
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.content;
/**
* File content
*
* @author amir aharon
*/
public class FileContent extends MmContent {
/**
* Constructor
*
* @param url URL
* @param size Content size
*/
public FileContent(String url, long size) {
super(url, "application/octet-stream", size);
}
/**
* Constructor
*
* @param url URL
*/
public FileContent(String url) {
super(url, "application/octet-stream");
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.content;
/**
* Live photo content
*
* @author amir aharon
*/
public class LivePhotoContent extends PhotoContent {
/**
* Constructor
*
* @param url URL
* @param encoding Encoding
* @param photo Photo
*/
public LivePhotoContent(String url, String encoding, byte[] photo) {
super(url, encoding, photo.length);
setData(photo);
}
/**
* Constructor
*
* @param url URL
* @aparam encoding Encoding
* @param size Content size
*/
public LivePhotoContent(String url, String encoding, long size) {
super(url, encoding, size);
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.content;
/**
* Live video content
*
* @author amir aharon
*/
public class LiveVideoContent extends VideoContent {
/**
* Livevideo URL constant
*/
public static final String URL = "capture://video";
/**
* Constructor
*
* @param encoding Encoding
*/
public LiveVideoContent(String encoding) {
super(URL, encoding);
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.content;
/**
* Multimedia content
*
* @author amir aharon
*/
public abstract class MmContent {
/**
* Content URL
*/
private String url;
/**
* Content size in bytes
*/
private long size;
/**
* Encoding
*/
private String encoding;
/**
* Data
*/
private byte[] data = null;
/**
* Content name
*/
private String name = null;
/**
* Constructor
*
* @param url URL
* @param encoding Encoding
*/
public MmContent(String url, String encoding) {
this.url = url;
this.encoding = encoding;
this.size = -1;
}
/**
* Constructor
*
* @param url URL
* @param encoding Encoding
* @param size Content size
*/
public MmContent(String url, String encoding, long size) {
this.url = url;
this.encoding = encoding;
this.size = size;
}
/**
* Returns the URL
*
* @return String
*/
public String getUrl() {
return url;
}
/**
* Returns the content size in bytes
*
* @return Size in bytes
*/
public long getSize() {
return size;
}
/**
* Returns the content size in Kbytes
*
* @return Size in Kbytes
*/
public long getKbSize() {
return size/1024;
}
/**
* Returns the content size in Mbytes
*
* @return Size in Mbytes
*/
public long getMbSize(){
return size/(1024*1024);
}
/**
* Returns the encoding type
*
* @return Encoding type
*/
public String getEncoding() {
return encoding;
}
/**
* Set the encoding type
*
* @param encoding Encoding type
*/
public void setEncoding(String encoding) {
this.encoding = encoding;
}
/**
* Returns the codec from the encoding type
*
* @return Codec name
*/
public String getCodec() {
int index = encoding.indexOf("/");
if (index != -1) {
return encoding.substring(index+1);
} else {
return encoding;
}
}
/**
* Get the name
*
* @return Name
*/
public String getName() {
if (name == null) {
// Extract filename from URL
int index = url.lastIndexOf('/');
if (index != -1) {
return url.substring(index+1);
} else {
return url;
}
} else {
// Return the name associated to the content
return name;
}
}
/**
* Returns the string representation of a content
*
* @return String
*/
public String toString() {
return url + " (" + size + " bytes)";
}
/**
* Returns the content data
*
* @return Data
*/
public byte[] getData() {
return data;
}
/**
* Sets the content data
*
* @param Data
*/
public void setData(byte[] data) {
this.data = data;
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.content;
/**
* Photo content
*
* @author amir aharon
*/
public class PhotoContent extends MmContent {
/**
* Constructor
*
* @param url URL
* @aparam encoding Encoding
* @param size Content size
*/
public PhotoContent(String url, String encoding, long size) {
super(url, encoding, size);
}
/**
* Constructor
*
* @param url URL
* @aparam encoding Encoding
*/
public PhotoContent(String url, String encoding) {
super(url, encoding);
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.content;
/**
* Video content
*
* @author amir aharon
*/
public class VideoContent extends MmContent {
/**
* Height
*/
private int height = 0;
/**
* Width
*/
private int width = 0;
/**
* Constructor
*
* @param url URL
* @aparam encoding Encoding
* @param size Content size
*/
public VideoContent(String url, String encoding, long size) {
super(url, encoding, size);
}
/**
* Constructor
*
* @param url URL
* @aparam encoding Encoding
*/
public VideoContent(String url, String encoding) {
super(url, encoding);
}
/**
* Set the width
*
* @param width width
*/
public void setWidth(int width) {
this.width = width;
}
/**
* Get the width
*
* @return width
*/
public int getWidth() {
return width;
}
/**
* Set the height
*
* @param height height
*/
public void setHeight(int height) {
this.height = height;
}
/**
* Get the height
*
* @return height
*/
public int getHeight() {
return height;
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.network.sip;
/**
* Feature tags
*
* @author amir aharon
*/
public class FeatureTags {
/**
* OMA IM feature tag
*/
public final static String FEATURE_OMA_IM = "+g.oma.sip-im";
/**
* 3GPP video share feature tag
*/
public final static String FEATURE_3GPP_VIDEO_SHARE = "+g.3gpp.cs-voice";
/**
* 3GPP image share feature tag
*/
public final static String FEATURE_3GPP_IMAGE_SHARE = "+g.3gpp.iari-ref=\"urn%3Aurn-7%3A3gpp-application.ims.iari.gsma-is\"";
/**
* 3GPP image share feature tag for RCS 2.0
*/
public final static String FEATURE_3GPP_IMAGE_SHARE_RCS2 = "+g.3gpp.app_ref=\"urn%3Aurn-7%3A3gpp-application.ims.iari.gsma-is\"";
/**
* RCS-e feature tag prefix
*/
public final static String FEATURE_RCSE = "+g.3gpp.iari-ref";
/**
* RCS-e image share feature tag
*/
public final static String FEATURE_RCSE_IMAGE_SHARE = "urn%3Aurn-7%3A3gpp-application.ims.iari.gsma-is";
/**
* RCS-e chat feature tag
*/
public final static String FEATURE_RCSE_CHAT = "urn%3Aurn-7%3A3gpp-application.ims.iari.rcse.im";
/**
* RCS-e file transfer feature tag
*/
public final static String FEATURE_RCSE_FT = "urn%3Aurn-7%3A3gpp-application.ims.iari.rcse.ft";
/**
* RCS-e presence discovery feature tag
*/
public final static String FEATURE_RCSE_PRESENCE_DISCOVERY = "urn%3Aurn-7%3A3gpp-application.ims.iari.rcse.dp";
/**
* RCS-e social presence feature tag
*/
public final static String FEATURE_RCSE_SOCIAL_PRESENCE = "urn%3Aurn-7%3A3gpp-application.ims.iari.rcse.sp";
/**
* RCS-e extension feature tag prefix
*/
public final static String FEATURE_RCSE_EXTENSION = "urn%3Aurn-7%3A3gpp-application.ims.iari.rcse";
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.network.sip;
import java.util.Hashtable;
import core.ims.network.sip.SipUtils;
/**
* Multipart content for SIP message
*
* @author amir aharon
*/
public class Multipart {
/**
* Boundary delimiter
*/
public final static String BOUNDARY_DELIMITER = "--";
/**
* MIME type
*/
public static final String MIME_TYPE = "multipart/mixed";
/**
* Content type header
*/
private final static String CONTENT_TYPE_HEADER = "Content-Type";
/**
* Parts
*/
private Hashtable<String, String> parts = new Hashtable<String, String>();
/**
* Constructor
*
* @param content Content parts
* @param boundary Boundary delimiter
*/
public Multipart(String content, String boundary) {
if ((content != null) && (boundary != null)) {
if (boundary.startsWith("\""))
{
// cutting the "
int lastIndex = boundary.lastIndexOf('"');
if (lastIndex != -1)
boundary = boundary.substring(1, lastIndex - 1);
else
boundary = boundary.substring(1);
}
String token = BOUNDARY_DELIMITER + boundary;
String[] fragments = content.split(token);
for (String fragment: fragments) {
String trimmedFragment = fragment.trim();
if ((trimmedFragment.length() > 0) && !BOUNDARY_DELIMITER.equals(trimmedFragment)) {
int begin = fragment.indexOf(SipUtils.CRLF+SipUtils.CRLF);
if (begin != -1) {
try {
// Extract content type
String type = fragment.substring(0, begin).trim();
// Extract content part
String part = fragment.substring(begin).trim();
// Extract MIME type from content type
int beginType = type.indexOf(CONTENT_TYPE_HEADER);
int endType = type.indexOf(SipUtils.CRLF, beginType);
String mime;
if (endType == -1) {
mime = type.substring(beginType+CONTENT_TYPE_HEADER.length()+1).trim();
} else {
mime = type.substring(beginType+CONTENT_TYPE_HEADER.length()+1, endType).trim();
}
// Add part in lowercase
parts.put(mime.toLowerCase(), part);
} catch(Exception e) {
// Nothing to do
}
}
}
}
}
}
/**
* Is a multipart
*
* @return Boolean
*/
public boolean isMultipart() {
return (parts.size() > 0);
}
/**
* Get part from its MIME-type
*
* @param type MIME-type
* @return Part as string
*/
public String getPart(String type) {
return parts.get(type.toLowerCase());
}
/**
* Get parts
*
* @return List of parts
*/
public Hashtable<String, String> getParts() {
return parts;
}
}
package core.ims.protocol.msrp;
import java.io.IOException;
import java.io.InputStream;
import java.util.Hashtable;
import java.util.logging.Logger;
/**
* Chunks receiver
*
* @author amir aharon
*/
public class ChunkReceiver extends Thread {
/**
* MSRP connection
*/
private MsrpConnection connection;
/**
* MSRP input stream
*/
private InputStream stream;
/**
* Termination flag
*/
private boolean terminated = false;
/**
* The logger
*/
private Logger logger = Logger.getLogger(this.getClass().getName());
/**
* Constructor
*
* @param connection MSRP connection
* @param stream TCP input stream
*/
public ChunkReceiver(MsrpConnection connection, InputStream stream) {
this.connection = connection;
this.stream = stream;
}
/**
* Returns the MSRP connection
*
* @return MSRP connection
*/
public MsrpConnection getConnection() {
return connection;
}
/**
* Terminate the receiver
*/
public void terminate() {
terminated = true;
try {
interrupt();
} catch(Exception e) {}
logger.info("Receiver is terminated");
}
/**
* Background processing
*/
public void run() {
try {
logger.info("Receiver is started");
// Background processing
while(!terminated) {
StringBuffer trace = new StringBuffer();
// Read first line of a new data chunk
StringBuffer line = readLine();
if (line.length() == 0) {
logger.info("End of stream");
return;
}
if (MsrpConnection.MSRP_TRACE_ENABLED) {
trace.append(line);
trace.append(MsrpConstants.NEW_LINE);
}
logger.info("Read a new chunk");
// Check the MSRP tag
String[] firstLineTags = line.toString().split(" ");
if ((firstLineTags.length < 3) || !firstLineTags[0].equals(MsrpConstants.MSRP_PROTOCOL)) {
logger.info("Not a MSRP message");
return;
}
// Get the transaction ID from the first line
String txId = firstLineTags[1];
logger.info("Transaction-ID: " + txId);
String end = MsrpConstants.END_MSRP_MSG + txId;
// Get response code or method name from the first line
int responseCode = -1;
String method = null;
try {
responseCode = Integer.parseInt(firstLineTags[2]);
logger.info("Response: " + responseCode);
} catch(NumberFormatException e) {
method = firstLineTags[2];
logger.info("Method: " + method);
}
// Data chunk
byte[] data = null;
// Read next lines
Hashtable<String, String> headers = new Hashtable<String, String>();
char continuationFlag = '\0';
long totalSize = 0;
while(continuationFlag == '\0') {
line = readLine();
if (MsrpConnection.MSRP_TRACE_ENABLED) {
trace.append(line);
trace.append(MsrpConstants.NEW_LINE);
}
// Test if there is a new line separating headers from the data
if (line.length() == 0) {
// Read data
String byteRange = headers.get(MsrpConstants.HEADER_BYTE_RANGE);
int chunkSize = 0;
if (byteRange != null) {
chunkSize = MsrpUtils.getChunkSize(byteRange);
totalSize = MsrpUtils.getTotalSize(byteRange);
}
logger.info("Read data (" + chunkSize + ")");
if (chunkSize > 0) {
// Use Byte-Range value to read directly the block of data
data = readChunkedData(chunkSize);
if (MsrpConnection.MSRP_TRACE_ENABLED) {
trace.append(new String(data));
trace.append(MsrpConstants.NEW_LINE);
}
} else {
// Read until terminating header is found
StringBuffer buffer = new StringBuffer();
StringBuffer dataline;
boolean endchunk = false;
while((!endchunk) && (buffer.length() < MsrpConstants.CHUNK_MAX_SIZE)) {
dataline = readLine();
if ((dataline.length()-1 == end.length()) && (dataline.toString().startsWith(end))) {
continuationFlag = dataline.charAt(dataline.length()-1);
logger.info("Continuous flag: " + continuationFlag);
endchunk = true;
} else {
if (buffer.length() > 0) {
buffer.append(MsrpConstants.NEW_LINE);
}
buffer.append(dataline);
}
}
data = buffer.toString().getBytes();
totalSize = data.length;
if (MsrpConnection.MSRP_TRACE_ENABLED) {
trace.append(new String(data));
trace.append(MsrpConstants.NEW_LINE);
trace.append(end);
trace.append(continuationFlag);
}
}
logger.info("Data: " + data.length);
} else
if (line.toString().startsWith(end)) {
continuationFlag = line.charAt(line.length()-1);
logger.info("Continuous flag: " + continuationFlag);
} else {
// It's an header
int index = line.indexOf(":");
String headerName = line.substring(0, index).trim();
String headerValue = line.substring(index+1).trim();
// Add the header in the list
headers.put(headerName, headerValue);
logger.info("Header: " + headerName);
}
}
// Process the received MSRP message
if (responseCode != -1) {
// Process MSRP response
if (MsrpConnection.MSRP_TRACE_ENABLED) {
System.out.println("<<< Receive MSRP response:\n" + trace);
}
connection.getSession().receiveMsrpResponse(responseCode, txId, headers);
} else {
// Process MSRP request
if (method.toString().equals(MsrpConstants.METHOD_SEND)) {
// Process a SEND request
if (MsrpConnection.MSRP_TRACE_ENABLED) {
System.out.println("<<< Receive MSRP SEND request:\n" + trace);
}
connection.getSession().receiveMsrpSend(txId, headers, continuationFlag, data, totalSize);
} else
if (method.toString().equals(MsrpConstants.METHOD_REPORT)) {
// Process a REPORT request
if (MsrpConnection.MSRP_TRACE_ENABLED) {
System.out.println("<<< Receive MSRP REPORT request:\n" + trace);
}
connection.getSession().receiveMsrpReport(txId, headers);
} else {
// Unknown request
logger.info("Unknown request received: " + method);
}
}
}
} catch(Exception e) {
if (terminated) {
logger.info("Chunk receiver thread terminated");
} else {
logger.severe("Chunk receiver has failed" + e);
// Notify the session listener that an error has occured
connection.getSession().getMsrpEventListener().msrpTransferError(e.getMessage());
}
terminated = true;
}
}
/**
* Read line
*
* @return String
* @throws IOException
*/
private StringBuffer readLine() throws IOException {
StringBuffer line = new StringBuffer();
int previous = -1;
int current = -1;
while((current = stream.read()) != -1) {
line.append((char)current);
if ((previous == MsrpConstants.CHAR_LF) && (current == MsrpConstants.CHAR_CR)) {
return line.delete(line.length()-2, line.length());
}
previous = current;
}
return line;
}
/**
* Read chunked data
*
* @param chunkSize Chunk size
* @return Data
* @throws IOException
*/
private byte[] readChunkedData(int chunkSize) throws IOException {
// Read data until chunk size is reached
byte[] result = null;
result = new byte[chunkSize];
int nbRead = 0;
int nbData = -1;
while((nbRead < chunkSize) && ((nbData = stream.read(result, nbRead, chunkSize-nbRead)) != -1)) {
nbRead += nbData;
}
stream.read(); // Read LF
stream.read(); // Read CR
return result;
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.protocol.msrp;
import java.io.IOException;
import java.io.OutputStream;
import java.util.logging.Logger;
/**
* Chunks sender
*
* @author amir aharon
*/
public class ChunkSender extends Thread {
/**
* MSRP connection
*/
private MsrpConnection connection;
/**
* MSRP output stream
*/
private OutputStream stream;
/**
* Buffer of chunks
*/
private FifoBuffer buffer = new FifoBuffer();
/**
* Termination flag
*/
private boolean terminated = false;
/**
* The logger
*/
private Logger logger = Logger.getLogger(this.getClass().getName());
/**
* Constructor
*
* @param connection MSRP connection
* @param stream TCP output stream
*/
public ChunkSender(MsrpConnection connection, OutputStream stream) {
this.connection = connection;
this.stream = stream;
}
/**
* Returns the MSRP connection
*
* @return MSRP connection
*/
public MsrpConnection getConnection() {
return connection;
}
/**
* Terminate the sender
*/
public void terminate() {
terminated = true;
buffer.unblockRead();
try {
interrupt();
} catch(Exception e) {}
logger.info("Sender is terminated");
}
/**
* Background processing
*/
public void run() {
try {
logger.info("Sender is started");
// Read chunk to be sent
byte chunk[] = null;
while ((chunk = (byte[])buffer.getMessage()) != null) {
// Write chunk to the output stream
if (MsrpConnection.MSRP_TRACE_ENABLED) {
System.out.println(">>> Send MSRP message:\n" + new String(chunk));
}
writeData(chunk);
}
} catch (Exception e) {
if (terminated) {
logger.info("Chunk sender thread terminated");
} else {
logger.severe("Chunk sender has failed" + e);
// Notify the msrp session listener that an error has occured
connection.getSession().getMsrpEventListener().msrpTransferError(e.getMessage());
}
}
}
/**
* Send a chunk
*
* @param chunk New chunk
* @throws IOException
*/
public void sendChunk(byte chunk[]) throws IOException {
if (connection.getSession().isFailureReportRequested()) {
buffer.putMessage(chunk);
} else {
sendChunkImmediately(chunk);
}
}
/**
* Send a chunk immediately
*
* @param chunk New chunk
* @throws IOException
*/
public void sendChunkImmediately(byte chunk[]) throws IOException {
if (MsrpConnection.MSRP_TRACE_ENABLED) {
System.out.println(">>> Send MSRP message:\n" + new String(chunk));
}
writeData(chunk);
}
/**
* Write data to the stream
*
* @param chunk Data chunck
* @throws IOException
*/
private synchronized void writeData(byte chunk[]) throws IOException {
// stream.write(chunk);
// stream.flush();
// test
connection.writeData(chunk);
}
}
package core.ims.protocol.msrp;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.logging.Logger;
/**
* Data chunks
*
* @author amir aharon
*/
public class DataChunks {
/**
* The logger
*/
private Logger logger = Logger.getLogger(this.getClass().getName());
/**
* Current transfered size in bytes
*/
private int currentSize = 0;
/**
* Cache used to save data chunks
*/
private ByteArrayOutputStream cache = new ByteArrayOutputStream();
/**
* Constructor
*/
public DataChunks() {
}
/**
* Add a new chunk
*
* @param data Data chunk
*/
public void addChunk(byte[] data) throws IOException {
cache.write(data, 0, data.length);
currentSize += data.length;
}
/**
* Get received data
*
* @return Byte array
*/
public byte[] getReceivedData() {
byte[] result=null;
try {
result = cache.toByteArray();
} catch (OutOfMemoryError e) {
logger.severe("Not enough memory to save data" + e);
}
return result;
}
/**
* Rset the cache
*/
public void resetCache() {
cache.reset();
currentSize = 0;
}
/**
* Returns the current size of the received chunks
*
* @return Size in bytes
*/
public int getCurrentSize() {
return currentSize;
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.protocol.msrp;
import java.util.Vector;
/**
* Fifo buffer
*
* @author JM. Auffret
*/
public class FifoBuffer {
/**
* Number of messages in the buffer
*/
private int numMessage = 0;
/**
* Buffer of messages
*/
private Vector<Object> fifo = new Vector<Object>();
/**
* Add a message in the buffer
*
* @param obj Message
*/
public synchronized void putMessage(Object obj) {
fifo.addElement(obj);
numMessage++;
notifyAll();
}
/**
* Read a message in the buffer. This is a blocking method until a
* message is received in the buffer.
*
* @return Message
*/
public synchronized Object getMessage() {
Object message = null;
if (numMessage == 0) {
try {
wait();
} catch (InterruptedException e) {
// Nothing to do
}
}
if (numMessage != 0) {
message = fifo.elementAt(0);
fifo.removeElementAt(0);
numMessage--;
notifyAll();
}
return message;
}
/**
* Read a message in the buffer. This is a blocking method until a timeout
* occurs or a message is received in the buffer.
*
* @param timeout Timeout
* @return Message
*/
public synchronized Object getMessage(int timeout) {
Object message = null;
if (numMessage == 0) {
try {
wait(timeout);
} catch (InterruptedException e) {
// Nothing to do
}
}
if (numMessage != 0) {
message = fifo.elementAt(0);
fifo.removeElementAt(0);
numMessage--;
notifyAll();
}
return message;
}
/**
* Unblock the reading
*/
public void unblockRead() {
synchronized (this) {
this.notifyAll();
}
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.protocol.msrp;
import java.io.IOException;
import java.util.logging.Logger;
import platform.network.NetworkFactory;
import platform.network.SocketConnection;
/**
* MSRP client connection
*
* @author amir aharon
*/
public class MsrpClientConnection extends MsrpConnection {
/**
* Remote IP address
*/
private String remoteAddress;
/**
* Remote TCP port number
*/
private int remotePort;
/**
* The logger
*/
private Logger logger = Logger.getLogger(this.getClass().getName());
/**
* Constructor
*
* @param session MSRP session
* @param remoteAddress Remote IP address
* @param remotePort Remote port number
*/
public MsrpClientConnection(MsrpSession session, String remoteAddress, int remotePort) {
super(session);
this.remoteAddress = remoteAddress;
this.remotePort = remotePort;
}
/**
* Returns the socket connection
*
* @return Socket
* @throws IOException
*/
public SocketConnection getSocketConnection() throws IOException {
logger.info("Open client socket to " + remoteAddress + ":" + remotePort);
SocketConnection socket = NetworkFactory.getFactory().createSocketClientConnection();
socket.open(remoteAddress, remotePort);
logger.info("Socket connected to " + socket.getRemoteAddress() + ":" + socket.getRemotePort());
return socket;
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.protocol.msrp;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Logger;
import platform.network.SocketConnection;
/**
* Abstract MSRP connection between two end points
*
* @author amir aharon
*/
public abstract class MsrpConnection {
/**
* MSRP traces enabled
*/
public static boolean MSRP_TRACE_ENABLED = false;
/**
* MSRP session
*/
private MsrpSession session;
/**
* Socket connection
*/
private SocketConnection socket = null;
/**
* Socket output stream
*/
private OutputStream outputStream = null;
/**
* Socket input stream
*/
private InputStream inputStream = null;
/**
* Chunk receiver
*/
private ChunkReceiver receiver;
/**
* Chunk sender
*/
private ChunkSender sender;
/**
* The logger
*/
private Logger logger = Logger.getLogger(this.getClass().getName());
/**
* Constructor
*
* @param session MSRP session
*/
public MsrpConnection(MsrpSession session) {
this.session = session;
}
/**
* Returns the MSRP session associated to the MSRP connection
*
* @return MSRP session
*/
public MsrpSession getSession() {
return session;
}
/**
* Open the connection
*
* @throws IOException
*/
public void open() throws IOException {
// Open socket connection
socket = getSocketConnection();
// Open I/O stream
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
// Create the chunk receiver
receiver = new ChunkReceiver(this, inputStream);
receiver.start();
// Create the chunk sender
sender = new ChunkSender(this, outputStream);
sender.start();
logger.info("Connection has been openned");
}
/**
* Open the connection
*
* @throws IOException
*/
public void setSocketConnection(SocketConnection sockConn) throws IOException {
// Open socket connection
socket = sockConn;
// Open I/O stream
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
// Create the chunk receiver
receiver = new ChunkReceiver(this, inputStream);
//receiver.start();
// Create the chunk sender
sender = new ChunkSender(this, outputStream);
//sender.start();
logger.info("Connection has been openned");
}
/**
* Open the connection with SO_TIMEOUT on the socket
*
* @param timeout Timeout value (in seconds)
* @throws IOException
*/
public void open(int timeout) throws IOException {
// Open socket connection
socket = getSocketConnection();
// Set SoTimeout
socket.setSoTimeout(timeout*1000);
// Open I/O stream
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
// Create the chunk receiver
receiver = new ChunkReceiver(this, inputStream);
receiver.start();
// Create the chunk sender
sender = new ChunkSender(this, outputStream);
sender.start();
logger.info("Connection has been openned");
}
/**
* Close the connection
*/
public void close() {
// Terminate chunk sender
if (sender != null) {
sender.terminate();
}
// Terminate chunk receiver
if (receiver != null) {
receiver.terminate();
}
// Close socket connection
try {
logger.info("Close the socket connection");
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
if (socket != null) {
socket.close();
}
} catch (Exception e) {
logger.severe("Can't close the socket correctly" + e);
}
logger.info("Connection has been closed");
}
/**
* Send a new data chunk
*
* @param chunk Data chunk
* @throws IOException
*/
public void sendChunk(byte chunk[]) throws IOException {
sender.sendChunk(chunk);
}
/**
* Send a new data chunk immediately
*
* @param chunk Data chunk
* @throws IOException
*/
public void sendChunkImmediately(byte chunk[]) throws IOException {
sender.sendChunkImmediately(chunk);
}
/**
* Returns the socket connection
*
* @return Socket
* @throws IOException
*/
public abstract SocketConnection getSocketConnection() throws IOException;
public void writeData(byte data[]) throws IOException
{
socket.write(data);
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.protocol.msrp;
/**
* MSRP contants
*
* @author amir aharon
*/
public interface MsrpConstants {
public static final String MSRP_PROTOCOL = "MSRP";
public static final String NEW_LINE = "\r\n";
public static final String END_MSRP_MSG = "-------";
public static final int FLAG_LAST_CHUNK = '$';
public static final int FLAG_MORE_CHUNK = '+';
public static final int FLAG_ABORT_CHUNK = '#';
public static final byte CHAR_SP = ' ';
public static final byte CHAR_LF = '\r';
public static final byte CHAR_CR = '\n';
public static final byte CHAR_MIN = '-';
public static final byte CHAR_DOUBLE_POINT = ':';
public static final String HEADER_BYTE_RANGE = "Byte-Range";
public static final String HEADER_STATUS = "Status";
public static final String HEADER_CONTENT_TYPE = "Content-Type";
public static final String HEADER_MESSAGE_ID = "Message-ID";
public static final String HEADER_TO_PATH = "To-Path";
public static final String HEADER_FROM_PATH = "From-Path";
public static final String HEADER_FAILURE_REPORT = "Failure-Report";
public static final String HEADER_SUCCESS_REPORT = "Success-Report";
public static final String METHOD_SEND = "SEND";
public static final String METHOD_REPORT = "REPORT";
public static final int RESPONSE_OK = 200;
public static final int CHUNK_MAX_SIZE = 10 * 1024;
public static final String COMMENT_OK = "OK";
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.protocol.msrp;
/**
* MSRP event listener
*
* @author amir aharon
*/
public interface MsrpEventListener {
/**
* Data has been transfered
*
* @param msgId Message ID
*/
public void msrpDataTransfered(String msgId);
/**
* Data has been received
*
* @param msgId Message ID
* @param data Received data
* @param mimeType Data mime-type
*/
public void msrpDataReceived(String msgId, byte[] data, String mimeType);
/**
* Data transfer in progress
*
* @param currentSize Current transfered size in bytes
* @param totalSize Total size in bytes
*/
public void msrpTransferProgress(long currentSize, long totalSize);
/**
* Data transfer has been aborted
*/
public void msrpTransferAborted();
/**
* Data transfer error
*
* @param error Error
*/
public void msrpTransferError(String error);
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.protocol.msrp;
/**
* MSRP exception
*
* @author amir aharon
*/
public class MsrpException extends Exception {
static final long serialVersionUID = 1L;
/**
* Constructor
*
* @param error Error message
*/
public MsrpException(String error) {
super(error);
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.protocol.msrp;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Logger;
import utils.IpAddressUtils;
/**
* MSRP manager
*
* @author amir aharon
*/
public class MsrpManager {
/**
* Local MSRP address
*/
private String localMsrpAddress;
/**
* Local MSRP port
*/
private int localMsrpPort;
/**
* MSRP session
*/
private MsrpSession msrpSession = null;
/**
* Session Id
*/
private long sessionId;
/**
* The logger
*/
private Logger logger = Logger.getLogger(this.getClass().getName());
/**
* Constructor
*
* @param localIpAddress Local MSRP address
* @param localMsrpPort Local MSRP port
*/
public MsrpManager(String localMsrpAddress, int localMsrpPort) {
this.localMsrpAddress = localMsrpAddress;
this.localMsrpPort = localMsrpPort;
this.sessionId = System.currentTimeMillis();
}
/**
* Returns the local MSRP port
*
* @return Port number
*/
public int getLocalMsrpPort() {
return localMsrpPort;
}
/**
* Get the local MSRP path
*
* @return MSRP path
*/
public String getLocalMsrpPath() {
if (IpAddressUtils.isIPv6(localMsrpAddress)) {
return "msrp://[" + localMsrpAddress + "]:" + localMsrpPort + "/" + sessionId + ";tcp";
} else {
return "msrp://" + localMsrpAddress + ":" + localMsrpPort + "/" + sessionId + ";tcp";
}
}
/**
* Return the MSRP session
*
* @return MSRP session
*/
public MsrpSession getMsrpSession() {
return msrpSession;
}
/**
* Open the MSRP session
*
* @throws IOException
*/
public void openMsrpSession() throws IOException {
if ((msrpSession == null) || (msrpSession.getConnection() == null)) {
throw new IOException("Session not yet created");
}
msrpSession.getConnection().open();
}
/**
* Open the connection with SO_TIMEOUT on the socket
*
* @param timeout Timeout value (in seconds)
* @throws IOException
*/
public void openMsrpSession(int timeout) throws IOException {
if ((msrpSession == null) || (msrpSession.getConnection() == null)) {
throw new IOException("Session not yet created");
}
msrpSession.getConnection().open(timeout);
}
/**
* Create a MSRP client session
*
* @param remoteHost Remote host
* @param remotePort Remote port
* @param remoteMsrpPath Remote MSRP path
* @param listener Event listener
* @return Created session
* @throws MsrpException
*/
public MsrpSession createMsrpClientSession(String remoteHost, int remotePort, String remoteMsrpPath, MsrpEventListener listener) throws MsrpException {
try {
logger.info("Create MSRP client end point at " + remoteHost + ":" + remotePort);
// Create a new MSRP session
msrpSession = new MsrpSession();
msrpSession.setFrom(getLocalMsrpPath());
msrpSession.setTo(remoteMsrpPath);
// Create a MSRP client connection
final MsrpConnection connection = new MsrpClientConnection(msrpSession, remoteHost, remotePort);
// Associate the connection to the session
msrpSession.setConnection(connection);
// Add event listener
msrpSession.addMsrpEventListener(listener);
// Return the created session
return msrpSession;
} catch(Exception e) {
logger.severe("Can't create the MSRP client session" + e);
throw new MsrpException("Create MSRP client session has failed");
}
}
/**
* Create a MSRP server session
*
* @param remoteMsrpPath Remote MSRP path
* @param listener Event listener
* @return Created session
* @throws MsrpException
*/
public MsrpSession createMsrpServerSession(String remoteMsrpPath, MsrpEventListener listener) throws MsrpException {
logger.info("Create MSRP server end point at " + localMsrpPort);
// Create a MSRP session
msrpSession = new MsrpSession();
msrpSession.setFrom(getLocalMsrpPath());
msrpSession.setTo(remoteMsrpPath);
// Create a MSRP server connection
final MsrpConnection connection = new MsrpServerConnection(msrpSession, localMsrpPort);
// Associate the connection to the session
msrpSession.setConnection(connection);
// Add event listener
msrpSession.addMsrpEventListener(listener);
// Return the created session
return msrpSession;
}
/**
* Send data chunks
*
* @param inputStream Input stream
* @param msgId Message ID
* @param contentType Content type
* @param contentSize Content size
* @throws MsrpException
*/
public void sendChunks(InputStream inputStream, String msgId, String contentType, long contentSize) throws MsrpException {
if (msrpSession == null) {
throw new MsrpException("MSRP session is null");
}
msrpSession.sendChunks(inputStream, msgId, contentType, contentSize);
}
/**
* Send an empty chunk
*
* @throws MsrpException
*/
public void sendEmptyChunk() throws MsrpException {
if (msrpSession == null) {
throw new MsrpException("MSRP session is null");
}
msrpSession.sendEmptyChunk();
}
/**
* Close the MSRP session
*/
public synchronized void closeSession() {
if (msrpSession != null) {
logger.info("Close the MSRP session");
try {
msrpSession.close();
} catch(Exception e) {
// Intentionally blank
}
msrpSession = null;
}
}
}
package core.ims.protocol.msrp;
import java.io.IOException;
import java.io.InputStream;
import java.util.Hashtable;
import java.util.logging.Logger;
/**
* this class is like {@link ChatReciever } only it is not
* a thread class, it is used to parse mrsp message and
* activate the appropriate mrsp api
* @author amir
*
*/
public class MsrpParser
{
/**
* MSRP input stream
*/
private InputStream stream;
/**
* MSRP session
*/
private MsrpSession session;
/**
* The logger
*/
private static Logger logger = Logger.getLogger("MsrpParser");
/**
* Constructor
*
* @param connection MSRP connection
* @param stream TCP input stream
*/
public MsrpParser() {
}
private void reset()
{
stream = null;
session = null;
}
/**
* parse the stream and activate the adequate api's in the msrp session
* if exists,
* @param stream
* @param session
*/
public void parse(InputStream stream, MsrpSession session)
{
reset();
this.stream = stream;
this.session = session;
try
{
StringBuffer trace = new StringBuffer();
// Read first line of a new data chunk
StringBuffer line = readLine();
if (line.length() == 0) {
logger.info("End of stream");
return;
}
if (MsrpConnection.MSRP_TRACE_ENABLED) {
trace.append(line);
trace.append(MsrpConstants.NEW_LINE);
}
logger.info("Read a new chunk");
// Check the MSRP tag
String[] firstLineTags = line.toString().split(" ");
if ((firstLineTags.length < 3) || !firstLineTags[0].equals(MsrpConstants.MSRP_PROTOCOL)) {
logger.info("Not a MSRP message");
return;
}
// Get the transaction ID from the first line
String txId = firstLineTags[1];
logger.info("Transaction-ID: " + txId);
String end = MsrpConstants.END_MSRP_MSG + txId;
// Get response code or method name from the first line
int responseCode = -1;
String method = null;
try {
responseCode = Integer.parseInt(firstLineTags[2]);
logger.info("Response: " + responseCode);
} catch(NumberFormatException e) {
method = firstLineTags[2];
logger.info("Method: " + method);
}
// Data chunk
byte[] data = null;
// Read next lines
Hashtable<String, String> headers = new Hashtable<String, String>();
char continuationFlag = '\0';
long totalSize = 0;
while(continuationFlag == '\0') {
line = readLine();
if (MsrpConnection.MSRP_TRACE_ENABLED) {
trace.append(line);
trace.append(MsrpConstants.NEW_LINE);
}
// Test if there is a new line separating headers from the data
if (line.length() == 0) {
// Read data
String byteRange = headers.get(MsrpConstants.HEADER_BYTE_RANGE);
int chunkSize = 0;
if (byteRange != null) {
chunkSize = MsrpUtils.getChunkSize(byteRange);
totalSize = MsrpUtils.getTotalSize(byteRange);
}
logger.info("Read data (" + chunkSize + ")");
if (chunkSize > 0) {
// Use Byte-Range value to read directly the block of data
data = readChunkedData(chunkSize);
if (MsrpConnection.MSRP_TRACE_ENABLED) {
trace.append(new String(data));
trace.append(MsrpConstants.NEW_LINE);
}
} else {
// Read until terminating header is found
StringBuffer buffer = new StringBuffer();
StringBuffer dataline;
boolean endchunk = false;
while((!endchunk) && (buffer.length() < MsrpConstants.CHUNK_MAX_SIZE)) {
dataline = readLine();
if ((dataline.length()-1 == end.length()) && (dataline.toString().startsWith(end))) {
continuationFlag = dataline.charAt(dataline.length()-1);
logger.info("Continuous flag: " + continuationFlag);
endchunk = true;
} else {
if (buffer.length() > 0) {
buffer.append(MsrpConstants.NEW_LINE);
}
buffer.append(dataline);
}
}
data = buffer.toString().getBytes();
totalSize = data.length;
if (MsrpConnection.MSRP_TRACE_ENABLED) {
trace.append(new String(data));
trace.append(MsrpConstants.NEW_LINE);
trace.append(end);
trace.append(continuationFlag);
}
}
logger.info("Data: " + data.length);
} else
if (line.toString().startsWith(end)) {
continuationFlag = line.charAt(line.length()-1);
logger.info("Continuous flag: " + continuationFlag);
} else {
// It's an header
int index = line.indexOf(":");
String headerName = line.substring(0, index).trim();
String headerValue = line.substring(index+1).trim();
// Add the header in the list
headers.put(headerName, headerValue);
logger.info("Header: " + headerName);
}
}
// Process the received MSRP message
if (responseCode != -1) {
// Process MSRP response
if (MsrpConnection.MSRP_TRACE_ENABLED) {
System.out.println("<<< Receive MSRP response:\n" + trace);
}
if (this.session != null)
session.receiveMsrpResponse(responseCode, txId, headers);
} else {
// Process MSRP request
if (method.toString().equals(MsrpConstants.METHOD_SEND)) {
// Process a SEND request
if (MsrpConnection.MSRP_TRACE_ENABLED) {
System.out.println("<<< Receive MSRP SEND request:\n" + trace);
}
if (this.session != null)
session.receiveMsrpSend(txId, headers, continuationFlag, data, totalSize);
} else
if (method.toString().equals(MsrpConstants.METHOD_REPORT)) {
// Process a REPORT request
if (MsrpConnection.MSRP_TRACE_ENABLED) {
System.out.println("<<< Receive MSRP REPORT request:\n" + trace);
}
if (this.session != null)
session.receiveMsrpReport(txId, headers);
} else {
// Unknown request
logger.info("Unknown request received: " + method);
}
}
}
catch(Exception e)
{
logger.severe("Chunk receiver has failed" + e);
// Notify the session listener that an error has occured
if (this.session != null)
session.getMsrpEventListener().msrpTransferError(e.getMessage());
}
}
/**
* Read line
*
* @return String
* @throws IOException
*/
private StringBuffer readLine() throws IOException {
StringBuffer line = new StringBuffer();
int previous = -1;
int current = -1;
while((current = stream.read()) != -1) {
line.append((char)current);
if ((previous == MsrpConstants.CHAR_LF) && (current == MsrpConstants.CHAR_CR)) {
return line.delete(line.length()-2, line.length());
}
previous = current;
}
return line;
}
/**
* Read chunked data
*
* @param chunkSize Chunk size
* @return Data
* @throws IOException
*/
private byte[] readChunkedData(int chunkSize) throws IOException {
// Read data until chunk size is reached
byte[] result = null;
result = new byte[chunkSize];
int nbRead = 0;
int nbData = -1;
while((nbRead < chunkSize) && ((nbData = stream.read(result, nbRead, chunkSize-nbRead)) != -1)) {
nbRead += nbData;
}
stream.read(); // Read LF
stream.read(); // Read CR
return result;
}
/**
* getting the chat session id from the message
* @param stream
* @return
*/
public String getChatSessionId(InputStream stream)
{
String chatSessionId = null;
this.stream = stream;
try
{
StringBuffer sb = readLine();
while (sb != null && sb.length() > 0)
{
String line = sb.toString();
if (line.startsWith(MsrpConstants.HEADER_TO_PATH))
{
// Getting the session-id
int slashIndex = line.lastIndexOf('/');
int semiIndex = line.lastIndexOf(';');
if (slashIndex != -1 && semiIndex != -1)
{
chatSessionId = line.substring(slashIndex + 1, semiIndex);
break;
}
}
sb = readLine();
}
}
catch (Exception e)
{
logger.severe("getChatSessionId has failed: " + e);
}
return chatSessionId;
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.protocol.msrp;
import java.io.IOException;
import java.util.logging.Logger;
import platform.network.NetworkFactory;
import platform.network.SocketConnection;
import platform.network.SocketServerConnection;
/**
* MSRP server connection
*
* @author amir aharon
*/
public class MsrpServerConnection extends MsrpConnection {
/**
* Local TCP port number
*/
private int localPort;
/**
* The logger
*/
private Logger logger = Logger.getLogger(this.getClass().getName());
/**
* Constructor
*
* @param session MSRP session
* @param localPort Local port number
*/
public MsrpServerConnection(MsrpSession session, int localPort) {
super(session);
this.localPort = localPort;
}
/**
* Returns the socket connection
*
* @return Socket
* @throws IOException
*/
public SocketConnection getSocketConnection() throws IOException {
logger.info("Open server socket at " + localPort);
SocketServerConnection socketServer = NetworkFactory.getFactory().createSocketServerConnection();
socketServer.open(localPort);
logger.info("Wait client connection");
SocketConnection socket = socketServer.acceptConnection();
logger.info("Socket connected to " + socket.getRemoteAddress() + ":" + socket.getRemotePort());
return socket;
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.protocol.msrp;
/**
* MSRP utility functions
*
* @author amir aharon
*/
public class MsrpUtils {
/**
* Get the chunk size
*
* @param header MSRP header
* @return Size in bytes
*/
public static int getChunkSize(String header) {
if (header == null) {
return -1;
}
int index1 = header.indexOf("-");
int index2 = header.indexOf("/");
if ((index1 != -1) && (index2 != -1)) {
try {
int lowByte = Integer.parseInt(header.substring(0, index1));
int highByte = Integer.parseInt(header.substring(index1+1, index2));
return (highByte - lowByte) + 1;
} catch (NumberFormatException e) {
return -1;
}
}
return -1;
}
/**
* Get the total size
*
* @param header MSRP header
* @return Size in bytes
*/
public static long getTotalSize(String header) {
if (header == null) {
return -1;
}
int index = header.indexOf("/");
if (index != -1) {
try {
return Long.parseLong(header.substring(index+1));
} catch (NumberFormatException e) {
return -1;
}
}
return -1;
}
}
\ No newline at end of file
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.protocol.msrp;
import java.util.Hashtable;
/**
* Report transaction
*
* @author amir aharon
*/
public class ReportTransaction extends Object {
/**
* MRSP report transaction timeout (in seconds)
*/
private final static int TIMEOUT = 3600; // TODO: which value ?
/**
* Reported size
*/
private long reportedSize = 0L;
/**
* Status code
*/
private int statusCode = -1;
/**
* Constructor
*/
public ReportTransaction() {
}
/**
* Notify report
*
* @param headers MSRP headers
*/
public void notifyReport(Hashtable<String, String> headers) {
synchronized(this) {
// Get status code
String status = headers.get(MsrpConstants.HEADER_STATUS);
if ((status != null) && (status.startsWith("000 "))) {
String[] parts = status.split(" ");
if (parts.length > 0) {
try {
statusCode = Integer.parseInt(parts[1]);
} catch(NumberFormatException e) {
statusCode = -1;
}
}
}
// Get reported size
String byteRange = headers.get(MsrpConstants.HEADER_BYTE_RANGE);
if (byteRange != null) {
reportedSize = MsrpUtils.getChunkSize(byteRange);
}
// Unblock semaphore
super.notify();
}
}
/**
* Wait report
*
* @return True if success else returns false
*/
public void waitReport() {
synchronized(this) {
try {
// Wait semaphore
super.wait(TIMEOUT * 1000);
} catch(InterruptedException e) {
// Nothing to do
}
}
}
/**
* Terminate transaction
*/
public void terminate() {
synchronized(this) {
// Unblock semaphore
super.notify();
}
}
/**
* Returns the reported data size
*
* @return Size in bytes
*/
public long getReportedSize() {
return reportedSize;
}
/**
* Returns the status
*
* @return Status or -1 in case of error
*/
public int getStatusCode() {
return statusCode;
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.protocol.msrp;
import java.util.Hashtable;
import provider.settings.RcsSettings;
/**
* Request transaction
*
* @author amir aharon
*/
public class RequestTransaction extends Object {
/**
* MRSP request transaction timeout (in seconds)
*/
private final static int TIMEOUT = RcsSettings.getInstance().getMsrpTransactionTimeout();
/**
* Received response
*/
private int receivedResponse = -1;
/**
* Constructor
*/
public RequestTransaction() {
}
/**
* Notify response
*
* @param code Response code
* @param headers MSRP headers
*/
public void notifyResponse(int code, Hashtable<String, String> headers) {
synchronized(this) {
// Set response code
this.receivedResponse = code;
// Unblock semaphore
super.notify();
}
}
/**
* Wait response
*/
public void waitResponse() {
synchronized(this) {
try {
// Wait semaphore
super.wait(TIMEOUT * 1000);
} catch(InterruptedException e) {
// Nothing to do
}
}
}
/**
* Terminate transaction
*/
public void terminate() {
synchronized(this) {
// Unblock semaphore
super.notify();
}
}
/**
* Is response received
*
* @return Boolean
*/
public boolean isResponseReceived() {
return (receivedResponse != -1);
}
/**
* Returns received response
*
* @return Code
*/
public int getResponse() {
return receivedResponse;
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.protocol.sdp;
/**
* Media attribute
*
* @author amir aharon
*/
public class MediaAttribute {
/**
* Attribute name
*/
private String name;
/**
* Attribute value
*/
private String value;
/**
* Constructor
*
* @param name Attribute name
* @param value Attribute value
*/
public MediaAttribute(String name, String value) {
this.name = name;
this.value = value;
}
/**
* Returns the attribute name
*
* @return Name
*/
public String getName() {
return name;
}
/**
* Returns the attribute value
*
* @return Value
*/
public String getValue() {
return value;
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.protocol.sdp;
import java.util.Vector;
/**
* Media description
*
* @author amir aharon
*/
public class MediaDescription {
/**
* Media name
*/
public String name;
/**
* Media port
*/
public int port;
/**
* Media protocol
*/
public String protocol;
/**
* Payload type
*/
public int payloadType;
/**
* Payload
*/
public String payload;
/**
* Media title
*/
public String mediaTitle;
/**
* Connection info
*/
public String connectionInfo;
/**
* Bandwidth info
*/
public String bandwidthInfo;
/**
* Encryption key
*/
public String encryptionKey;
/**
* Media attributes
*/
public Vector<MediaAttribute> mediaAttributes = new Vector<MediaAttribute>();
/**
* Constructor
*
* @param name Media name
* @param port Media port
* @param protocol Media protocol
* @param payload Media payload
*/
public MediaDescription(String name, int port, String protocol, String payload) {
this.name = name;
this.port = port;
this.protocol = protocol;
this.payload = payload;
try {
this.payloadType = Integer.parseInt(payload);
} catch (Exception e) {
this.payloadType = -1;
}
}
public MediaAttribute getMediaAttribute(String name) {
MediaAttribute attribute = null;
if (mediaAttributes != null) {
for (int i = 0; i < mediaAttributes.size(); i++) {
MediaAttribute entry = (MediaAttribute)mediaAttributes.elementAt(i);
if (entry.getName().equals(name)) {
attribute = entry;
break;
}
}
}
return attribute;
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.protocol.sdp;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Vector;
/**
* Generic parser
*
* @author amir aharon
*/
class Parser {
/**
* Buffer
*/
private Vector<Integer> buffer = new Vector<Integer>();
/**
* Unget a token
*
* @param tk Token
*/
public void ungetToken(String tk) {
byte token[] = tk.getBytes();
for (int i = 0; i < token.length; i++) {
buffer.insertElementAt(Integer.valueOf(token[token.length - i - 1]), 0);
}
}
/**
* Get a token
*
* @param input Input stream
* @param tk Token
* @return Token value
*/
public boolean getToken(ByteArrayInputStream input, String tk) {
boolean found = false;
ByteArrayOutputStream bout = new ByteArrayOutputStream();
skipWhitespace(input);
if (input.available() > 0) {
int ch = readChar(input);
while (ch != '=' && ch != '\n' && ch != '\r' && ch != -1) {
bout.write(ch);
ch = readChar(input);
}
bout.write(ch);
}
String token = new String(bout.toByteArray());
if (tk.equals(token)) {
found = true;
} else {
ungetToken(token);
}
return found;
}
/**
* Get a line
*
* @param input Input stream
* @return Line
*/
public String getLine(ByteArrayInputStream input) {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
if (input.available() > 0) {
int ch = readChar(input);
while (ch != '\n' && ch != '\r' && ch != -1) {
bout.write(ch);
ch = readChar(input);
}
}
String line = new String(bout.toByteArray());
return line;
}
/**
* Skip whitespace
*
* @param input Input stream
*/
private void skipWhitespace(ByteArrayInputStream input) {
int ch = readChar(input);
while (ch == ' ' || ch == '\n' || ch == '\r') {
ch = readChar(input);
}
buffer.insertElementAt(Integer.valueOf(ch), 0);
}
/**
* Read char
*
* @param input Input stream
*/
private int readChar(ByteArrayInputStream input) {
int ch;
if (buffer.size() > 0) {
ch = ((Integer)buffer.elementAt(0)).intValue();
buffer.removeElementAt(0);
} else {
ch = input.read();
}
return ch;
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.protocol.sdp;
import java.io.ByteArrayInputStream;
import java.util.Vector;
/**
* SDP parser
*
* @author amir aharon
*/
public class SdpParser extends Parser {
/**
* Session description
*/
public SessionDescription sessionDescription = new SessionDescription();
/**
* Media description
*/
public Vector<MediaDescription> mediaDescriptions = new Vector<MediaDescription>();
/**
* Input stream
*/
private ByteArrayInputStream bin = null;
/**
* Constructor
*
* @param data Data
*/
public SdpParser(byte data[]) {
bin = new ByteArrayInputStream(data);
if (getToken(bin, "v=")) {
parseSessionDescription();
parseMediaDescriptions();
}
}
/**
* Parse session description
*/
private void parseSessionDescription() {
// Protocol version
sessionDescription.version = getLine(bin);
// Origin
if (getToken(bin, "o=")) {
sessionDescription.origin = getLine(bin);
}
// Session name
if (getToken(bin, "s=")) {
sessionDescription.sessionName = getLine(bin);
}
// Session and media Information
if (getToken(bin, "i=")) {
sessionDescription.sessionInfo = getLine(bin);
}
// URI
if (getToken(bin, "u=")) {
sessionDescription.uri = getLine(bin);
}
// E-Mail
if (getToken(bin, "e=")) {
sessionDescription.email = getLine(bin);
}
// Phone number
if (getToken(bin, "p=")) {
sessionDescription.phone = getLine(bin);
}
// Connection information
if (getToken(bin, "c=")) {
sessionDescription.connectionInfo = getLine(bin);
}
// Bandwidth information
if (getToken(bin, "b=")) {
sessionDescription.bandwidthInfo = getLine(bin);
}
// Time description
sessionDescription.timeDescriptions = new Vector<TimeDescription>();
while(getToken(bin, "t=")) {
TimeDescription timeDescription = parseTimeDescription();
this.sessionDescription.timeDescriptions.addElement(timeDescription);
}
// Time zone adjustments
if (getToken(bin, "z=")) {
sessionDescription.timezoneAdjustment = getLine(bin);
}
// Encryption key
if (getToken(bin, "k=")) {
sessionDescription.encryptionKey = getLine(bin);
}
// Session attributes
sessionDescription.sessionAttributes = new Vector<MediaAttribute>();
while(getToken(bin, "a=")) {
String sessionAttribute = getLine(bin);
int index = sessionAttribute.indexOf(':');
if (index > 0) {
String name = sessionAttribute.substring(0, index);
String value = sessionAttribute.substring(index + 1);
MediaAttribute attribute = new MediaAttribute(name, value);
sessionDescription.sessionAttributes.addElement(attribute);
}
}
}
/**
* Parse time description
*
* @return Time description
*/
private TimeDescription parseTimeDescription() {
TimeDescription td = new TimeDescription();
// Time the session is active
td.timeActive = getLine(bin);
// Repeat times
td.repeatTimes = new Vector<String>();
while(getToken(bin, "r=")) {
String repeatTime = getLine(bin);
td.repeatTimes.addElement(repeatTime);
}
return td;
}
/**
* Parse media descriptions
*/
private void parseMediaDescriptions() {
while(getToken(bin, "m=")) {
Vector<MediaDescription> descs = new Vector<MediaDescription>();
// Media name and transport address
String line = getLine(bin);
int end = line.indexOf(' ');
String name = line.substring(0, end);
int start = end + 1;
end = line.indexOf(' ', start);
int port = Integer.parseInt(line.substring(start, end));
start = end + 1;
end = line.indexOf(' ', start);
String protocol = line.substring(start, end);
String payload;
start = end + 1;
end = line.indexOf(' ', start);
while (end != -1) {
payload = line.substring(start, end);
descs.addElement(new MediaDescription(name, port, protocol, payload));
start = end + 1;
end = line.indexOf(' ', start);
}
payload = line.substring(start);
descs.addElement(new MediaDescription(name, port, protocol, payload));
// Session and media information
if (getToken(bin, "i=")) {
String mediaTitle = getLine(bin);
for (int i = 0; i < descs.size(); i++) {
descs.elementAt(i).mediaTitle = mediaTitle;
}
}
// Connection information
if (getToken(bin, "c=")) {
String connectionInfo = getLine(bin);
for (int i = 0; i < descs.size(); i++) {
descs.elementAt(i).connectionInfo = connectionInfo;
}
}
// Bandwidth information
if (getToken(bin, "b=")) {
String bandwidthInfo = getLine(bin);
for (int i = 0; i < descs.size(); i++) {
descs.elementAt(i).bandwidthInfo = bandwidthInfo;
}
}
// Encryption key
if (getToken(bin, "k=")) {
String encryptionKey = getLine(bin);
for (int i = 0; i < descs.size(); i++) {
descs.elementAt(i).encryptionKey = encryptionKey;
}
}
// Media attributes
while(getToken(bin, "a=")) {
line = getLine(bin);
int index = line.indexOf(':');
if (index > 0) {
String nameAttribute = line.substring(0, index);
String valueAttribute = line.substring(index + 1);
MediaAttribute attribute = new MediaAttribute(nameAttribute, valueAttribute);
// Dispatch for specific payload
if ((nameAttribute.equalsIgnoreCase("rtpmap")) && (valueAttribute.indexOf(' ') != -1)) {
// Add the attribute only for same payload
for (int i = 0; i < descs.size(); i++) {
if (valueAttribute.startsWith(descs.elementAt(i).payload)) {
descs.elementAt(i).mediaAttributes.addElement(attribute);
}
}
} else {
for (int i = 0; i < descs.size(); i++) {
descs.elementAt(i).mediaAttributes.addElement(attribute);
}
}
}
}
// Copy in media descriptions
for(int i = 0; i < descs.size(); i++) {
mediaDescriptions.addElement((MediaDescription)descs.elementAt(i));
}
}
}
/**
* Returns session attribute
*
* @param name Attribute name
* @return Attribute
*/
public MediaAttribute getSessionAttribute(String name) {
if (sessionDescription != null) {
return sessionDescription.getSessionAttribute(name);
} else {
return null;
}
}
/**
* Returns a media description
*
* @param name Media name
* @return Media
*/
public MediaDescription getMediaDescription(String name) {
MediaDescription description = null;
if (mediaDescriptions != null) {
for (int i = 0; i < mediaDescriptions.size(); i++) {
MediaDescription entry = (MediaDescription)mediaDescriptions.elementAt(i);
if (entry.name.equals(name)) {
description = entry;
break;
}
}
}
return description;
}
/**
* Returns media descriptions
*
* @param name Media name
* @return Medias
*/
public Vector<MediaDescription> getMediaDescriptions(String name) {
Vector<MediaDescription> result = new Vector<MediaDescription>();
if (mediaDescriptions != null) {
for (int i = 0; i < mediaDescriptions.size(); i++) {
MediaDescription entry = (MediaDescription)mediaDescriptions.elementAt(i);
if (entry.name.equals(name)) {
result.add(entry);
}
}
}
return result;
}
/**
* Returns all media descriptions
*
* @return Medias
*/
public Vector<MediaDescription> getMediaDescriptions() {
return mediaDescriptions;
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.protocol.sdp;
import utils.IpAddressUtils;
/**
* SDP utility functions
*
* @author amir aharon
*/
public class SdpUtils {
/**
* Extract the remote host address from the connection info
*
* @param connectionInfo Connection info
* @return Address
*/
public static String extractRemoteHost(String connectionInfo) {
// c=IN IP4 172.20.138.145
String[] tokens = connectionInfo.split(" ");
if (tokens.length > 2) {
return tokens[2];
} else {
return null;
}
}
/**
* Format "IN IP" attribute (4 or 6)
*
* @param address IP address
* @return "IN IP4 address" or "IN IP6 address"
*/
public static String formatAddressType(String address) {
if (IpAddressUtils.isIPv6(address)) {
return "IN IP6 " + address;
} else {
return "IN IP4 " + address;
}
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.protocol.sdp;
import java.util.Vector;
/**
* Session description
*
* @author amir aharon
*/
public class SessionDescription {
public Vector<TimeDescription> timeDescriptions;
public Vector<MediaAttribute> sessionAttributes;
public boolean connectionIncluded;
public String version;
public String origin;
public String sessionName;
public String sessionInfo;
public String uri;
public String email;
public String phone;
public String connectionInfo;
public String bandwidthInfo;
public String timezoneAdjustment;
public String encryptionKey;
public MediaAttribute getSessionAttribute(String name) {
MediaAttribute attribute = null;
if (sessionAttributes != null) {
for (int i = 0; i < sessionAttributes.size(); i++) {
MediaAttribute entry = (MediaAttribute) sessionAttributes.elementAt(i);
if (entry.getName().equals(name)) {
attribute = entry;
break;
}
}
}
return attribute;
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.protocol.sdp;
import java.util.Vector;
/**
* Time description
*
* @author amir aharon
*/
public class TimeDescription {
public String timeActive;
public Vector<String> repeatTimes;
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.service;
/**
* IMS service error
*
* @author amir aharon
*/
public class ImsServiceError extends Error {
static final long serialVersionUID = 1L;
/**
* Unexpected exception occurs in the module (e.g. internal exception)
*/
public final static int UNEXPECTED_EXCEPTION = 1;
/**
* Session initiation has failed (e.g. 408 timeout)
*/
public final static int SESSION_INITIATION_FAILED = 2;
/**
* Session initiation has been declined (e.g. 603 Decline or 486 Busy)
*/
public final static int SESSION_INITIATION_DECLINED = 3;
/**
* Session initiation has been cancelled (e.g. 487 Session terminated)
*/
public final static int SESSION_INITIATION_CANCELLED = 4;
/**
* Error code
*/
private int code;
/**
* Constructor
*
* @param code Error code
*/
public ImsServiceError(int code) {
super();
this.code = code;
}
/**
* Constructor
*
* @param code Error code
* @param msg Detail message
*/
public ImsServiceError(int code, String msg) {
super(msg);
this.code = code;
}
/**
* Returns the error code
*
* @return Error code
*/
public int getErrorCode() {
return code;
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.service;
/**
* Listener of events sent during an IMS session
*
* @author JM. Auffret
*/
public interface ImsSessionListener {
/**
* Session is started
*/
public void handleSessionStarted();
/**
* Session has been aborted
*/
public void handleSessionAborted();
/**
* Session has been terminated by remote
*/
public void handleSessionTerminatedByRemote();
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.service;
/**
* Session-ID generator
*
* @author amir aharon
*/
public class SessionIdGenerator {
/**
* Counter
*/
private static long current = System.currentTimeMillis();
/**
* Returns a unique integer ID
*
* @return ID
*/
public static synchronized String getNewId() {
current++;
return ""+current;
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.service.im;
import java.util.Date;
/**
* Instant message
*
* @author amir aharon
*/
public class InstantMessage{
/**
* MIME type
*/
public static final String MIME_TYPE = "text/plain";
/**
* Remote user
*/
private String remote;
/**
* Text message
*/
private String message;
/**
* Receipt date of the message
*/
private Date receiptAt;
/**
* Receipt date of the message on the server (i.e. CPIM date)
*/
private Date serverReceiptAt;
/**
* Message Id
*/
private String msgId;
/**
* Flag indicating that an IMDN "displayed" is requested for this message
*/
private boolean imdnDisplayedRequested = false;
/**
* Constructor for outgoing message
*
* @param messageId Message Id
* @param remote Remote user
* @param message Text message
* @param imdnDisplayedRequested Flag indicating that an IMDN "displayed" is requested
*/
public InstantMessage(String messageId, String remote, String message, boolean imdnDisplayedRequested) {
this.msgId = messageId;
this.remote = remote;
this.message = message;
this.imdnDisplayedRequested = imdnDisplayedRequested;
Date date = new Date();
this.receiptAt = date;
this.serverReceiptAt = date;
}
/**
* Constructor for incoming message
*
* @param messageId Message Id
* @param remote Remote user
* @param message Text message
* @param imdnDisplayedRequested Flag indicating that an IMDN "displayed" is requested
* @param serverReceiptAt Receipt date of the message on the server
*/
public InstantMessage(String messageId, String remote, String message, boolean imdnDisplayedRequested, Date serverReceiptAt) {
this.msgId = messageId;
this.remote = remote;
this.message = message;
this.imdnDisplayedRequested = imdnDisplayedRequested;
this.receiptAt = new Date();
this.serverReceiptAt = serverReceiptAt;
}
// /**
// * Constructor
// *
// * @param
// */
// public InstantMessage() {
// this.remote = source.readString();
// this.message = source.readString();
// this.msgId = source.readString();
// this.imdnDisplayedRequested = source.readInt() != 0;
// this.receiptAt = new Date(source.readLong());
// this.serverReceiptAt = new Date(source.readLong());
// }
/**
* Describe the kinds of special objects contained in this Parcelable's
* marshalled representation
*
* @return Integer
*/
public int describeContents() {
return 0;
}
// /**
// * Write parcelable object
// *
// * @param dest The Parcel in which the object should be written
// * @param flags Additional flags about how the object should be written
// */
// public void writeToParcel(Parcel dest, int flags) {
// dest.writeString(remote);
// dest.writeString(message);
// dest.writeString(msgId);
// dest.writeInt(imdnDisplayedRequested ? 1 : 0);
// dest.writeLong(receiptAt.getTime());
// dest.writeLong(serverReceiptAt.getTime());
// }
// /**
// * Parcelable creator
// */
// public static final Parcelable.Creator<InstantMessage> CREATOR
// = new Parcelable.Creator<InstantMessage>() {
// public InstantMessage createFromParcel(Parcel source) {
// return new InstantMessage(source);
// }
//
// public InstantMessage[] newArray(int size) {
// return new InstantMessage[size];
// }
// };
/**
* Returns the text message
*
* @return String
*/
public String getTextMessage() {
return message;
}
/**
* Returns the message Id
*
* @return message Id
*/
public String getMessageId(){
return msgId;
}
/**
* Returns the remote user
*
* @return Remote user
*/
public String getRemote() {
return remote;
}
/**
* Returns true if the IMDN "displayed" has been requested
*
* @return Boolean
*/
public boolean isImdnDisplayedRequested() {
return imdnDisplayedRequested;
}
/**
* Returns the receipt date of the message
*
* @return Date
*/
public Date getDate() {
return receiptAt;
}
/**
* Returns the receipt date of the message on the server
*
* @return Date
*/
public Date getServerDate() {
return serverReceiptAt;
}
}
/*******************************************************************************
* Software Name : RCS IMS Stack
*
* Copyright (C) 2010 France Telecom S.A.
*
* 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 core.ims.service.im.chat;
import core.ims.service.ImsServiceError;
/**
* Chat error
*
* @author amir aharon
*/
public class ChatError extends ImsServiceError {
static final long serialVersionUID = 1L;
/**
* Unexpected exception occurs in the module (e.g. internal exception)
*/
public final static int UNEXPECTED_EXCEPTION = 0x01;
/**
* IM session initiation has failed (e.g. 408 timeout)
*/
public final static int SESSION_INITIATION_FAILED = 0x02;
/**
* Session initiation has been declined (e.g. 486 Busy)
*/
public final static int SESSION_INITIATION_DECLINED = 0x03;
/**
* Session initiation has been cancelled (e.g. 487 Session terminated)
*/
public final static int SESSION_INITIATION_CANCELLED = 0x04;
/**
* Media session has failed (e.g. MSRP failure)
*/
public final static int MEDIA_SESSION_FAILED = 0x05;
/**
* Subscription to conference package has failed
*/
public final static int SUBSCRIBE_CONFERENCE_FAILED = 0x06;
/**
* Constructor
*
* @param code Error code
*/
public ChatError(int code) {
super(code);
}
/**
* Constructor
*
* @param code Error code
* @param msg Detail message
*/
public ChatError(int code, String msg) {
super(code, msg);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment