How to set max concurrent logins per user in apache SshServer - kotlin

I need to limit the concurrent sessions allowed per user in an apache SshServer. I found two references to this functionality, but they seem to be obsolete.
Here's the original patch back in 2010:
https://issues.apache.org/jira/browse/SSHD-95
I also found this reference to its usage:
http://apache-mina.10907.n7.nabble.com/How-to-set-max-count-connections-in-sshd-service-td44764.html
Which refers to a SshServer.setProperty() method.
I'm using sshd-core 2.4.0, and this method is absent from SshServer, I can't see any obvious replacement, and I can't find any documentation on what has happened to it or how I'm supposed to do this now.
I still see the MAX_CONCURRENT_SESSIONS key in ServerFactoryManager, so I assume the functionality is still in there somewhere, but I can't find where I need to set it.
Here's what the setup of the server looks like (it's for an SFTP server, but that shouldn't matter for the problem at ahnd, I thnk):
private val server = SshServer.setUpDefaultServer().apply {
val sftpSubsystemFactory = SftpSubsystemFactory().apply {
addSftpEventListener(sftpEventListener)
}
port = sftpPort
host = "localhost"
keyPairProvider = when {
sftpKeyname.isEmpty() -> throw IllegalStateException("No key name for SFTP, aborting!")
sftpKeyname == "NO_RSA" -> {
log.warn("Explicitly using NO_RSA, sftp encryption is insecure!")
SimpleGeneratorHostKeyProvider(File("host.ser").toPath())
}
else -> KeyPairProvider.wrap(loadKeyPair(sftpKeyname))
}
setPasswordAuthenticator { username, password, _ ->
// current evil hack to prevent users from opening more than one session
if (activeSessions.any { it.username == username }) {
log.warn("User attempted multiple concurrent sessions!")
throw IllegalUserStateException("User already has a session!")
} else {
log.debug("new session for user $username")
// throws AuthenticationException
authenticationService.checkCredentials(username, password)
true
}
}
subsystemFactories = listOf(sftpSubsystemFactory)
fileSystemFactory = YellowSftpFilesystemFactory(ftpHome)
start()
log.info("SFTP server started on port $port")
}

(From my comment) you can set the property directly:
server.apply {
properties[ServerFactoryManager.MAX_CONCURRENT_SESSIONS] = 50L
}

Related

agora - onUserJoined - how to differentiate specific broadcaster/host

onUserJoined provides UID which is then used to set up remote video.
in live stream feature when there are two hosts streaming in one channel and if another audience joins later then how can that audience tell which uid is for which host.
Note that onUserJoined does call in random order.
https://docs.agora.io/en/All/API%20Reference/java/classio_1_1agora_1_1rtc_1_1_i_rtc_channel_event_handler.html#a65fd197a39824219aedc2cba81296e82
Use case:
2 hosts already streaming in one channel. 1 of the host is original host and another is a co-host(got invited into the channel)
an audience joins the channel. onUserJoined callback is triggered twice and given the remote UID. That audience now needs to know who is the original host and related his UID and who is the co-host and his related UID.
You basically Answered your self
LIVE_BROADCASTING profile: This callback notifies the app when the host joins the channel. If other hosts are already in the channel, the SDK also reports to the app on the existing hosts. We recommend having at most 17 hosts in a channel.
I finally found a solution for that issue by informing all users that will enter the channel after the Orignal Host by the uid of the orignal host
and you can do this by using sendStreamMessage() function
First joinChannelSuccess triggers after original host login
which will return uid of the original host - and we will save it in a variable.
Then, use sendStreamMessage() to send this uid for all new users
and that by using this function which will be called when userJoined triggers
check this code
int _orignalHost = 'the uid';
_addListener() {
_engine.setEventHandler(RtcEngineEventHandler(
**joinChannelSuccess:** (channel, uid, elapsed) {
setState(() {
isJoined = true;
});
},
**userJoined:** (uid, elapsed) {
remoteUids.add(uid);
setState(() {});
},
// this trriger when you recive the mesage
**streamMessage:** (int uid, int streamId, Uint8List data) {
// save it in _orignalHost variable for the audince
},
streamMessageError:
(int uid, int streamId, ErrorCode error, int missed, int cached) {
},
));
}
Future<void> _onNewUserJoin() async {
try {
var streamId = await _engine
.createDataStreamWithConfig(DataStreamConfig(false, false));
if (streamId != null) {
await _engine.sendStreamMessage(
streamId, Uint8List.fromList(utf8.encode(_orignalHost)));
}
_controller.clear();
} catch (e) {
}
}
you can check full code for StreamMessage:
https://github.com/AgoraIO/Agora-Flutter-SDK/blob/master/example/lib/examples/advanced/stream_message/stream_message.dart
Also, You can check this for more info (anoter solution)
https://docs.agora.io/en/Real-time-Messaging/faq/audience_event?platform=Android

How do I force AWS Cognito to retrieve an IdentityId from the server?

In the iOS SDK (v2.4.8) I can't logout a user and then login as a different user correctly.
The (correct) cognityIdentityId returned by AWS for the first user (since an app start) is also returned for the second user (unless the app is restarted). This gives access to the AWSCognitoDataset of one user by another.
I think this is because the iOS SDK has cached the id and the documented call to clear that cache, doesn't fully work.
When logging in:
// one-off initialisation
self.credentialsProvider = AWSCognitoCredentialsProvider(regionType:AWSRegionType.USEast1, identityPoolId:Constants.CognitoIdentityPoolId)
let configuration = AWSServiceConfiguration(region:AWSRegionType.USEast1, credentialsProvider:self.credentialsProvider)
AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = configuration
…
// I get idToken from my external provider serice (Auth0)
func doAmazonLogin(idToken: String, success : () -> (), _ failure : (NSError) -> ()) {
var task: AWSTask?
//Initialize clients for new idToken
if self.credentialsProvider?.identityProvider.identityProviderManager == nil || idToken != Application.sharedInstance.retrieveIdToken() {
let logins = [Constants.CognitoIDPUrl: idToken]
task = self.initializeClients(logins)
} else {
//Use existing clients
self.credentialsProvider?.invalidateCachedTemporaryCredentials()
task = self.credentialsProvider?.getIdentityId()
}
//Make login
task!.continueWithBlock { (task: AWSTask!) -> AnyObject! in
if (task.error != nil) {
failure(task.error!)
} else {
// the task result will contain the identity id
let cognitoId:String? = task.result as? String
self.customIdentityProviderManager!.addToken(Constants.CognitoIDPUrl, value:idToken)
//Store Cognito token in keychain
Application.sharedInstance.storeCognitoToken(cognitoId)
success()
}
return nil
}
}
func initializeClients(logins: [NSObject:AnyObject]?) -> AWSTask? {
//Create identity provider managet with logins
let manager = CustomIdentityProviderManager(tokens: logins!)
self.credentialsProvider?.setIdentityProviderManagerOnce(manager)
return self.credentialsProvider?.getIdentityId()
}
When logging out:
// Clear ALL saved values for this provider (identityId, credentials, logins). [docs][1]
let keychain = A0SimpleKeychain(service:"…")
keychain.clearAll()
I've also tried adding:
credentialsProvider!.clearCredentials()
credentialsProvider!.clearKeychain()
Is anyone using the AWS iOS SDK and has coded logout successfully such that a new user can login cleanly?
There is the oddly named method credentialsProvider.setIdentityProviderManagerOnce() - I can't find this documented but its name suggests that it should only be called once per session. But if keychain.clearAll() removes logins then one would need to call setIdentityProviderManagerOnce each time a new user logins in in order to setup logins each time.
Can you describe your login/logout flow a bit more? Cognito doesn't support multiple logins from the same provider per identity, so it sounds like, unless you're using multiple, it isn't actually changing the identity.
In any case, have you tried the clearKeyChain method on the credentials provider? It's largely for use cases like this - clearing everything.

Genesys Platform : Get Call Details From Sip Server

I want to get Call Details from Genesys Platform SIP Server.
And Genesys Platform has Platform SDK for .NET .
Anybod has a SIMPLE sample code which shows how to get call details using Platform SDK for .NET [ C# ] from SIP Server?
Extra Notes:
Call Details : especially i wanted to get AgentId for a given call
and
From Sip Server : I am not sure if Sip Server is the best candiate to
take call details. So open to other suggestions/ alternatives
You can build a class that monitor DN actions. Also you watch specific DN or all DN depending what you had to done. If its all about the call, this is the best way to this.
Firstly, you must define a TServerProtocol, then you must connect via host,port and client info.
var endpoint = new Endpoint(host, port, config);
//Endpoint backupEndpoint = new Endpoint("", 0, config);
protocol = new TServerProtocol(endpoint)
{
ClientName = clientName
};
//Sync. way;
protocol.Open();
//Async way;
protocol.BeginOpen();
I always use async way to do this. I got my reason thou :) You can detect when connection open with event that provided by SDK.
protocol.Opened += new EventHandler(OnProtocolOpened);
protocol.Closed += new EventHandler(OnProtocolClosed);
protocol.Received += new EventHandler(OnMessageReceived);
protocol.Error += new EventHandler(OnProtocolError);
Here there is OnMessageReceived event. This event where the magic happens. You can track all of your call events and DN actions. If you go genesys support site. You'll gonna find a SDK reference manual. On that manual quiet easy to understand there lot of information about references and usage.
So in your case, you want agentid for a call. So you need EventEstablished to do this. You can use this in your recieve event;
var message = ((MessageEventArgs)e).Message;
// your event-handling code goes here
switch (message.Id)
{
case EventEstablished.MessageId:
var eventEstablished = message as EventEstablished;
var AgentID = eventEstablished.AgentID;
break;
}
You can lot of this with this usage. Like dialing, holding on a call inbound or outbound even you can detect internal calls and reporting that genesys platform don't.
I hope this is clear enough.
If you have access to routing strategy and you can edit it. You can add some code to strategy to send the details you need to some web server (for example) or to DB. We do such kind of stuff in our strategy. After successful routing block as a post routing strategy sends values of RTargetPlaceSelected and RTargetAgentSelected.
Try this:
>
Genesyslab.Platform.Contacts.Protocols.ContactServer.Requests.JirayuGetInteractionContent
JirayuGetInteractionContent =
Genesyslab.Platform.Contacts.Protocols.ContactServer.Requests.JirayuGetInteractionContent.Create();
JirayuGetInteractionContent.InteractionId = "004N4aEB63TK000P";
Genesyslab.Platform.Commons.Protocols.IMessage respondingEventY =
contactserverProtocol.Request(JirayuGetInteractionContent);
Genesyslab.Platform.Commons.Collections.KeyValueCollection keyValueCollection =
((Genesyslab.Platform.Contacts.Protocols.ContactServer.Events.EventGetInteractionContent)respondingEventY).InteractionAttributes.AllAttributes;
We are getting AgentID and Place as follows,
Step-1:
Create a Custome Command Class and Add Chain of command In ExtensionSampleModule class as follows,
class LogOnCommand : IElementOfCommand
{
readonly IObjectContainer container;
ILogger log;
ICommandManager commandManager;
public bool Execute(IDictionary<string, object> parameters, IProgressUpdater progress)
{
if (Application.Current.Dispatcher != null && !Application.Current.Dispatcher.CheckAccess())
{
object result = Application.Current.Dispatcher.Invoke(DispatcherPriority.Send, new ExecuteDelegate(Execute), parameters, progress);
return (bool)result;
}
else
{
// Get the parameter
IAgent agent = parameters["EnterpriseAgent"] as IAgent;
IIdentity workMode = parameters["WorkMode"] as IIdentity;
IAgent agentManager = container.Resolve<IAgent>();
Genesyslab.Desktop.Modules.Core.Model.Agents.IPlace place = agentManager.Place;
if (place != null)
{
string Place = place.PlaceName;
}
else
log.Debug("Place object is null");
CfgPerson person = agentManager.ConfPerson;
if (person != null)
{
string AgentID = person.UserName;
log.DebugFormat("Place: {0} ", AgentID);
}
else
log.Debug("AgentID object is null");
}
}
}
// In ExtensionSampleModule
readonly ICommandManager commandManager;
commandManager.InsertCommandToChainOfCommandAfter("MediaVoiceLogOn", "LogOn", new
List<CommandActivator>() { new CommandActivator()
{ CommandType = typeof(LogOnCommand), Name = "OnEventLogOn" } });
enter code here
IInteractionVoice interaction = (IInteractionVoice)e.Value;
switch (interaction.EntrepriseLastInteractionEvent.Id)
{
case EventEstablished.MessageId:
var eventEstablished = interaction.EntrepriseLastInteractionEvent as EventEstablished;
var genesysCallUuid = eventEstablished.CallUuid;
var genesysAgentid = eventEstablished.AgentID;
.
.
.
.
break;
}

What permissions do I need to grant to run RavenDB in Server mode?

I'm reading through Rob Ashton's excellent blog post on RavenDB:
http://codeofrob.com/archive/2010/05/09/ravendb-an-introduction.aspx
and I'm working through the code as I read. But when I try to add an index, I get a 401 error. Here's the code:
class Program
{
static void Main(string[] args)
{
using (var documentStore = new DocumentStore() { Url = "http://localhost:8080" })
{
documentStore.Initialise();
documentStore.DatabaseCommands.PutIndex(
"BasicEntityBySomeData",
new IndexDefinition<BasicEntity, BasicEntity>()
{
Map = docs => from doc in docs
where doc.SomeData != null
select new
{
SomeData = doc.SomeData
},
});
string entityId;
using (var documentSession = documentStore.OpenSession())
{
var entity = new BasicEntity()
{
SomeData = "Hello, World!",
SomeOtherData = "This is just another property",
};
documentSession.Store(entity);
documentSession.SaveChanges();
entityId = entity.Id;
var loadedEntity = documentSession.Load<BasicEntity>(entityId);
Console.WriteLine(loadedEntity.SomeData);
var docs = documentSession.Query<BasicEntity>("BasicEntityBySomeData")
.Where("SomeData:Hello~")
.WaitForNonStaleResults()
.ToArray();
docs.ToList().ForEach(doc => Console.WriteLine(doc.SomeData));
Console.Read();
}
}
}
It throws the 401 error when on the line that makes the PutIndex() call. Any ideas what permissions I need to apply? And where I need to apply them?
What do you mean by Server mode? Do you mean simply executing Raven.Server?
I've not had to do anything special client-side to get that to work, although I have had to run Raven.Server with elevated privileges because I'm not sure the code to ask for relevant permissions is quite working as intended. (Actually, I'll raise a query about that on the mailing list)
You shouldn't be getting a 401 error unless you've changed the configuration of Raven.Server.
If you're running the server, you can browse to it directly using the url specified in configuration (localhost:8080 by default) - make sure it's actually running and working as intended before continuing with troubleshooting

Unable to get presence of roster by using smack, openfire

I am new to smack API. I am trying to develop a chat application where I was trying for setting and getting the presence.
When I change the presence of a user, its working perfectly fine and it is getting reflected in the Openfire Server.
But when I tries to get the Presence of a user, I am always getting the status as 'unavailable' even if his presence in openfire is showing as 'available'.
I am using the following code to set the status.
Presence presence = new Presence(Presence.Type.available);
presence.setStatus("Online, Programmatically!");
presence.setPriority(24);
presence.setMode(Presence.Mode.available);
user.getConnection().sendPacket(presence);
I am using the Roster class to get the presence as follows.
Roster roster = avatar.getRoster();
Collection<RosterEntry> entries = roster.getEntries();
for(RosterEntry rosterEntry: entries) {
String user = rosterEntry.getUser();
Presence presence = roster.getPresence(user);
System.out.println("Presence : "+presence); // 1
System.out.println("Presence type: "+presence.getType()); // 2
System.out.println("Presence mode: "+presence.getMode()); // 3
}
Line No 1 alwasys gives 'unavailable' while line number 2 and 3 always give null
I am not able to figure out the cause of this problem. Please help me to resolve this issue.
Thanks in advance.
Using RosterListener is the proper solution to this problem. There is no reason that code should have a Thread.sleep() in order to make it work properly.
Roster roster = con.getRoster();
roster.addRosterListener(new RosterListener() {
// Ignored events public void entriesAdded(Collection<String> addresses) {}
public void entriesDeleted(Collection<String> addresses) {}
public void entriesUpdated(Collection<String> addresses) {}
public void presenceChanged(Presence presence) {
System.out.println("Presence changed: " + presence.getFrom() + " " + presence);
}
});
(source: http://www.igniterealtime.org/builds/smack/docs/latest/documentation/roster.html)
the problem is that after logging in immediately, it is gonna take some time for the presence of users to get updated.So between logging in and calling the online buddies function there should be a thread.sleep() for a few seconds.Then the online contacts will be retrieved. I did that and was able to retrieve them.
after login use
Thread.sleep(5000);
use in the beginiing of the method also
I had the same problem and searched for a while before finding what the problem was. In fact, you don't need to do a Thread.sleep(). The problem is that you don't have the "permission" to get the Presence of other users.
To solve the problem, just go in Openfire admin -> your user options -> Roster // Then just set the subscription of the buddy you wanna get the presence to "both" (both users can view each other presence).
Hope that is helps.
Edit : In fact you need to add a Thread.sleep() before getting the roster from the connection. Without the Thread.sleep(), sometimes it works, sometimes not...
I fixed it adding:
if (!roster.isLoaded())
roster.reloadAndWait();
after:
Roster roster = Roster.getInstanceFor(connection);
Ref: Smack 4.1.0 android Roster not displaying
This full code
public void getRoaster(final Callback<List<HashMap<String, String>>> callback) {
final Roster roster = Roster.getInstanceFor(connection);
boolean success = true;
if (!roster.isLoaded())
try {
roster.reloadAndWait();
} catch (SmackException.NotLoggedInException | SmackException.NotConnectedException | InterruptedException e) {
android.util.Log.e(AppConstant.PUBLIC_TAG, TAG + " " + e.getMessage());
success = false;
}
if (!success) {
if (callback != null) {
callback.onError(new Throwable());
}
}
Collection<RosterEntry> entries = roster.getEntries();
List<HashMap<String, String>> maps = new ArrayList<HashMap<String, String>>(entries.size());
for (RosterEntry entry : entries) {
HashMap<String, String> map = new HashMap<String, String>(3);
Presence presence = roster.getPresence(entry.getUser());
map.put(ROASTER_KEY, entry.getName());
map.put(ROASTER_BARE_JID, entry.getUser());
map.put(PRESENCE_TYPE, presence.isAvailable() == true ? PRESENCE_ONLINE : PRESENCE_OFFLINE);
maps.add(map);
}
if (maps != null && maps.size() > 0 && callback != null) {
callback.onSuccess(maps);
} else {
callback.onError(new Throwable());
}
}