How to get a new socket connection mid-session? - c

I'm using C-style TCP sockets with send() and recv(). I have a connection running between user A and user B, where user A acts as a server and user B acts as a client.
I want to have a passive user C, which does not communicate anything, but receives data from user A. However, the new passive user C can join the session at any time. A might send C different packets than what it would send B.. I imagine it would be best for A-C to communicate on a different port than A-B
How can this connection be made (without threading, or the like) in an arbitrary point of communication?
edit still unsolved.

You could setup a listener that detects new connections, and mirror traffic to all open sockets. I recently wrote what I mean in C#: (i'll see whether I can quickly turn that into a C sample)
This example only accepts a fixed nr of incoming connections at the start, but it is dead easy to change that.
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Linq;
public class Demo
{
static IList<Socket> StartServer(int numberOfClients)
{
using(Socket main = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
main.Bind(new IPEndPoint(IPAddress.Any, 9050));
main.Listen(numberOfClients);
var clients = Enumerable
.Range(1,numberOfClients)
.Select(i => {
Console.WriteLine("Waiting for 1 more client...");
Socket client = main.Accept();
Console.WriteLine("Connected to {0}", client.RemoteEndPoint);
return client; })
.ToList();
main.Close();
return clients;
}
}
public static void Main()
{
var clients = StartServer(4);
while(clients.Count()>1) // still a conversation
{
var copyList = clients.ToList();
Console.WriteLine("Monitoring {0} sockets...", copyList.Count);
Socket.Select(copyList, null, null, 10000000);
foreach(Socket client in copyList)
{
byte[] data = new byte[1024];
int recv = client.Receive(data);
if (recv == 0)
{
Console.WriteLine("Client {0} disconnected.", client.RemoteEndPoint);
client.Close();
clients.Remove(client);
}
else
foreach (var other in clients.Except(new [] {client}))
other.Send(data, recv, SocketFlags.None);
}
}
Console.WriteLine("Last client disconnected, bye");
}
}

You can simply open 2 sockets on the server A, and bind them on 2 different ports.
Then use select function on the 2 created socket file descriptors.
Select will return first time when one of the 2 clients make a connect. Remember that on server side, after accepting a connect, you should set the returned new file descriptor (with FD_SET) in order to make select listen to events that will happen on the new socket( which returned from accept).

Related

Data Logging from Cogent Datahub to a Database using gamma scripting based on a timer

Can you guys please help me with writing a gamma script for logging data into a database table? The tags are inside a domain created in OPC DA of Cogent Datahub. The only condition that needs to be satisfied is the script should be logging all points in the domain every one second along with their value and timestamp.
require ("Application");
require ("ODBCThreadSupport");
require ("Time");
require ("Quality");
class LogData Application
{
DSN = "your ODBC DSN name"; // The DSN name to use for the database
connection
username = "Database_User"; // The user name for connecting to the
database
password = "*****"; // The password for connecting to the database
tablename = "table1"; // The name of the database table
cachefile = "C:\Users\AppData\cache.txt"; // Base name for the disk cache file
domain = "Domain name"; // The domain in which to log all points
tableclass;
thread;
mappedPoints = new Dictionary();
prevcount = 0;
}
/* If there is something we only want to perform on the first connection, we can
test
* is_first_connect to perform the code only once.
*/
method LogData.onConnect()
{
princ ("Connection succeeded\n");
if (.thread.is_first_connect)
{
// Start the sequence defined by the AddInitStage calls in the constructor
.thread.BeginAsyncInit();
}
}
/* If the connection fails after having been
* connected, this method is called.
*/
method LogData.onConnectFail()
{
princ ("Connection closed: ", SQLResult.Description, "\n");
}
/* Map the table in the set of table definitions that matches the name in
.tablename
* into a Gamma class. This lets us easily convert between class instances and
rows
* in the table.
*/
method LogData.mapTable(name, tabledefinitions)
{
//princ("Mapping table\n");
.tableclass = .thread.ClassFromTable(name, tabledefinitions);
//princ("Table class = ", .tableclass, "\n");
}
method LogData.startLogging()
{
.registerPoints();
}
/* Set up the timer or event handler functions to write to the table. */
method LogData.registerPoints()
{
/* Find all points in the domain */
local info = datahub_domaininfo(.domain)[0];
if (info.n_points != .prevcount)
{
local points = datahub_points(.domain, nil, nil);
local pointsym;
princ(info.n_points - .prevcount, " new points are being added to
logging\n");
with point in points do
{
// Filter out branch points
if ((point.flags & 0x30) == 0)
{
pointsym = symbol(string(point.domain,":", point.name));
if (!.mappedPoints.contains(pointsym))
{
local PointName = string(pointsym);
.TimerEvery(01,`(#self).writeData(#PointName));
//.mappedPoints.add(pointsym, pointsym);
}
}
}
.prevcount = info.n_points;
}
}
method LogData.writeData(pointsymbol)
{
local row = new (.tableclass);
local pttime, ptltime;
local timestring;
local point;
// Generate a timestamp in database-independent format to the millisecond.
// Many databases strip the milliseconds from a timestamp, but it is harmless
// to provide them in case the database can store them.
point = PointMetadata(pointsymbol);
//princ(point,"\n");
if (point && number_p(point.value))
{
pttime = WindowsTimeToUnixTime(point.timestamp);
//princ(point,"\n");
ptltime = localtime(pttime);
//princ(ptltime,"\n");
if (!ptltime)
ptltime = localtime(0);
timestring = format("{'%04d-%02d-%02d %02d:%02d:%02d'}",
ptltime.year+1900, ptltime.mon+1, ptltime.mday, ptltime.hour, ptltime.min,
ptltime.sec);
//princ(timestring,"\n");
// Fill the row. Since we mapped the table into a Gamma class, we can
access
// the rows in the column as member variables of the mapped class.
row.ptname = string(pointsymbol);
row.ptvalue = point.value;
row.pttime = timestring;
// Perform the insertion. In this case we are providing no callback on
completion.
.thread.Insert(row, nil);
}
}
/* Write the 'main line' of the program here. */
method LogData.constructor ()
{
// Create and configure the database connection object
.thread = new ODBCThread();
.thread.Configure(.DSN, .username, .password, STORE_AND_FORWARD, .cachefile, 0);
// Query the table and map it to a class for each insertion. We want to run an
asynchronous event
// within the asynchronous initialization stage, so to do that we specify the
special method
// cbInitStage as the callback function of our asynchronous event
(GetTableInfo). We deal with
// the return from the GetTableInfo in the onSuccess argument of the init stage.
.thread.AddInitStage(`(#.thread).GetTableInfo("", "", (#.tablename),
"TABLE,VIEW",
`(#.thread).cbInitStage()),
`(#self).mapTable(#.tablename, SQLTables), nil);
//.thread.AddInitStage(`(#.thread).GetTableInfo("", "", (#.tablename),
"TABLE,VIEW",
// `(#self).mapTable(#.tablename, SQLTables)),
`(#.thread).cbInitStage(), nil);
// Do not start writing data to the table until we have successfully created and
mapped
// the table to a class. If we wanted to start writing data immediately, then
we would
// create the table class beforehand instead of querying the database for the
table
// definition. Then, even if the database were unavailable we could still cache
to the
// local disk until the database was ready.
.thread.AddInitStage(nil, `(#self).startLogging(), nil);
// Set up the callback functions for various events from the database thread
.thread.OnConnectionSucceeded = `(#self).onConnect();
.thread.OnConnectionFailed = `(#self).onConnectFail();
.thread.OnFileSystemError = `princ("File System Error: ", SQLResult, "\n");
.thread.OnODBCError = `princ("ODBC Error: ", SQLResult, "\n");
.thread.OnExecuteStored = nil;
.thread.Start();
// Create a menu item in the system tray that allows us to open a window to
monitor
// the performance of the ODBC thread. The menu strings can be edited as
desired.
.AddCustomSubMenu("ODBC Logging");
.AddCustomMenuItem("Monitor Performance",
`(#.thread).CreateMonitorWindow((#self), "ODBC Monitor"));
// Automatically update the point list every 1 seconds in case new points are v
added
// to the domain.
//.TimerEvery(01, `(#self).registerPoints());
}
/* Any code to be run when the program gets shut down. */
method LogData.destructor ()
{
if (instance_p(.thread))
destroy(.thread);
}
/* Start the program by instantiating the class. */
ApplicationSingleton (LogData);
Major parts of this Gamma script are the constructor,destructor,classes and methods. This program first initializes an ODBC connection using provided details and write each row of data using 'registerpoints' and 'writedata' methods. Please find additional details of each lines from comments in the program.

Cisco Call Manager JTAPI support for SIP protocol

I am trying to monitor SIP devices located on Cisco Call manager via JTAPI. I have installed JTAPI plugin and try to run its sample makeCall scenario.
CUCM version : 9.1.2.10000-28
When I list the controlled device addresses of the provider, it only returns devices with SCCP protocol (skinny phones) but not return devices with SIP device protocol. There are already SIP based devices added into the controlled device list of the provider on CUCM.
JtapiPeer peer = JtapiPeerFactory.getJtapiPeer(null);
/* connect to the provider */
String providerString = hostname;
providerString += ";login=" + login;
providerString += ";passwd=" + passwd;
Provider provider = peer.getProvider(providerString);
/* wait for it to come into service */
final Condition inService = new Condition();
provider.addObserver(new ProviderObserver() {
public void providerChangedEvent (ProvEv [] eventList) {
if (eventList == null) return;
for (int i = 0; i < eventList.length; ++i) {
if (eventList[i] instanceof ProvInServiceEv) {
inService.set();
}
}
}
});
inService.waitTrue();
for(Address address : provider.getAddresses()){
System.out.println(address.getName());
}
Is there any other config, etc.. that I need to do in order to list SIP phones as well?
Thanks.
JTAPI applications can only control Cisco Unified IP Phone 7900 Series that run SIP, which includes Cisco Unified IP 7970 phones. Which model you are using?
http://www.cisco.com/c/en/us/td/docs/voice_ip_comm/cucm/jtapi_dev/9_1_1/jtapidevguide/featsupported.html#wp1148307

Algorithm for concurrent access to resource(s) on database

Some time ago we implemented a warehouse management app that keeps track of quantities of each product we have in the store. We solved the problem of concurrent access to data with database locks (select for update), but this approach led to poor performance when many clients try to consume product quantities from the same store. Note that we manage only a small set of product types (less than 10) so the degree of concurrency could be heavy (also, we don't care of stock re-fill). We thought to split each resource quantity in smaller "buckets", but this approach could lead to starvation for clients that try to consume a quantity that is bigger than each bucket capacity: we should manage buckets merge and so on...
My question is: there are some broadly-accepted solutions to this problem? I also looked for academic articles but the topic seems too wide.
P.S. 1:
our application runs in a clustered environment, so we cannot rely on the application concurrency control. The question aims to find an algorithm that structures and manages the data in a different way than a single row, but keeping all the advantages that a db transaction (using locks or not) has.
P.S. 2: for your info, we manage a wide number of similar warehouses, the example focuses on a single one, but we keep all the data in one db (prices are all the same, etc).
Edit: The setup below will still work on a cluster if you use a queueing program that can coordinate among multiple processes / servers, e.g. RabbitMQ.
You can also use a simpler queueing algorithm that only uses the database, with the downside that it requires polling (whereas a system like RabbitMQ allows threads to block until a message is available). Create a Requests table with a column for unique requestIds (e.g. a random UUID) that acts as the primary key, a timestamp column, a respourceType column, and an integer requestedQuantity column. You'll also need a Logs table with a unique requestId column that acts as the primary key, a timestamp column, a resourceType column, an integer requestQuantity column, and a boolean/tinyint/whatever success column.
When a client requests a quantity of ResourceX it generates a random UUID and adds a row to the Requests table using the UUID as the requestId, and then polls the Logs table for the requestId. If the success column is true then the request succeeded, else it failed.
The server with the database assigns one thread or process to each resource, e.g. ProcessX is in charge of ResourceX. ProcessX retrieves all rows from the Requests table where resourceType = ResourceX, sorted by timestamp, and then deletes them from Requests; it then processes each request in order, decrementing an in-memory counter for each successful request, and at the end of processing the requests it updates the quantity of ResourceX on the Resources table. It then writes each request and its success status to the Logs table. It then retrieves all of the requests from Requests where requestType = RequestX again, etc.
It may be slightly more efficient to use an autoincrement integer as the Requests primary key, and to have ProcessX sort by primary key instead of by timestamp.
One option is to assign one DAOThread per resource - this thread is the only thing that accesses that resource's database table so that there's no locking at the database level. Workers (e.g. web sessions) request resource quantities using a concurrent queue - the example below uses a Java BlockingQueue, but most languages will have some sort of concurrent queue implementation you can use.
public class Request {
final int value;
final BlockingQueue<ReturnMessage> queue;
}
public class ReturnMessage {
final int value;
final String resourceType;
final boolean isSuccess;
}
public class DAOThread implements Runnable {
private final int MAX_CHANGES = 10;
private String resourceType;
private int quantity;
private int changeCount = 0;
private DBTable table;
private BlockingQueue<Request> queue;
public DAOThread(DBTable table, BlockingQueue<Request> queue) {
this.table = table;
this.resourceType = table.select("resource_type");
this.quantity = table.select("quantity");
this.queue = queue;
}
public void run() {
while(true) {
Requester request = queue.take();
if(request.value <= quantity) {
quantity -= request.value;
if(++changeCount > MAX_CHANGES) {
changeCount = 0;
table.update("quantity", quantity);
}
request.queue.offer(new ReturnMessage(request.value, resourceType, true));
} else {
request.queue.offer(new ReturnMessage(request.value, resourceType, false));
}
}
}
}
public class Worker {
final Map<String, BlockingQueue<Request>> dbMap;
final SynchronousQueue<ReturnMessage> queue = new SynchronousQueue<>();
public class WorkerThread(Map<String, BlockingQueue<Request>> dbMap) {
this.dbMap = dbMap;
}
public boolean request(String resourceType, int value) {
dbMap.get(resourceType).offer(new Request(value, queue));
return queue.take();
}
}
The Workers send resource requests to the appropriate DAOThread's queue; the DAOThread processes these requests in order, either updating the local resource quantity if the request's value doesn't exceed the quantity and returning a Success, else leaving the quantity unchanged and returning a Failure. The database is only updated after ten updates to reduce the amount of IO; the larger MAX_CHANGES is, the more complicated it will be to recover from system failure. You can also have a dedicated IOThread that does all of the database writes - this way you don't need to duplicate any logging or timing (e.g. there ought to be a Timer that flushes the current quantity to the database after every few seconds).
The Worker uses a SynchronousQueue to wait for a response from the DAOThread (a SynchronousQueue is a BlockingQueue that can only hold one item); if the Worker is running in its own thread the you may want to replace this with a standard multi-item BlockingQueue so that the Worker can process the ReturnMessages in any order.
There are some databases e.g. Riak that have native support for counters, so this might improve your IO thoughput and reduce or eliminate the need for a MAX_CHANGES.
You can further increase throughput by introducing BufferThreads to buffer the requests to the DAOThreads.
public class BufferThread implements Runnable {
final SynchronousQueue<ReturnMessage> returnQueue = new SynchronousQueue<>();
final int BUFFERSIZE = 10;
private DAOThread daoThread;
private BlockingQueue<Request> queue;
private ArrayList<Request> buffer = new ArrayList<>(BUFFERSIZE);
private int tempTotal = 0;
public BufferThread(DAOThread daoThread, BlockingQueue<Request> queue) {
this.daoThread = daoThread;
this.queue = queue;
}
public void run() {
while(true) {
Request request = queue.poll(100, TimeUnit.MILLISECONDS);
if(request != null) {
tempTotal += request.value;
buffer.add(request);
}
if(buffer.size() == BUFFERSIZE || request == null) {
daoThread.queue.offer(new Request(tempTotal, returnQueue));
ReturnMessage message = returnQueue.take();
if(message.isSuccess()) {
for(Request request: buffer) {
request.queue.offer(new ReturnMessage(request.value, daoThread.resourceType, message.isSuccess));
}
} else {
// send unbuffered requests to DAOThread to see if any can be satisfied
for(Request request: buffer) {
daoThread.queue.offer(request);
}
}
buffer.clear();
tempTotal = 0;
}
}
}
}
The Workers send their requests to the BufferThreads, who then wait until they've buffered BUFFERSIZE requests or have waited for 100ms for a request to come through the buffer (Request request = queue.poll(100, TimeUnit.MILLISECONDS)), at which point they forward the buffered message to the DAOThread. You can have multiple buffers per DAOThread - rather than sending a Map<String, BlockingQueue<Request>> to the Workers you instead send a Map<String, ArrayList<BlockingQueue<Request>>>, one queue per BufferThread, with the Worker either using a counter or a random number generator to determine which BufferThread to send a request to. Note that if BUFFERSIZE is too large and/or if you have too many BufferThreads then Workers will suffer from long pause times as they wait for the buffer to fill up.

Why is this JeroMQ (ZeroMQ port) benchmark so slow?

I would like to use this library I found, it's a pure java port (not a wrapper) of zeromq.
I am trying to test it and while it claims some good numbers, the test I am performing is giving rather poor results and it's even performed locally (client and serve on the same machine). I'm sure it's something I am doing wrong. It takes approx. 5 seconds to execute this 10.000 messages loop.
All I did is take the Hello world example and removed pause and sysouts. Here is the code:
The Server:
package guide;
import org.jeromq.ZMQ;
public class hwserver{
public static void main(String[] args) throws Exception{
// Prepare our context and socket
ZMQ.Context context = ZMQ.context(1);
ZMQ.Socket socket = context.socket(ZMQ.REP);
System.out.println("Binding hello world server");
socket.bind ("tcp://*:5555");
while (true) {
byte[] reply = socket.recv(0);
String requestString = "Hello" ;
byte[] request = requestString.getBytes();
socket.send(request, 0);
}
}
}
The Client:
package guide;
import org.jeromq.ZMQ;
public class hwclient{
public static void main(String[] args){
ZMQ.Context context = ZMQ.context(1);
ZMQ.Socket socket = context.socket(ZMQ.REQ);
socket.connect ("tcp://localhost:5555");
System.out.println("Connecting to hello world server");
long start = System.currentTimeMillis();
for(int request_nbr = 0; request_nbr != 10_000; request_nbr++) {
String requestString = "Hello" ;
byte[] request = requestString.getBytes();
socket.send(request, 0);
byte[] reply = socket.recv(0);
}
long end = System.currentTimeMillis();
System.out.println(end-start);
socket.close();
context.term();
}
}
Is is possible to fix this code and get some decent numbers?
You're doing round-trip request-reply, and this will be just as slow using the C++ libzmq. You will only get fast performance on JeroQM, ZeroMQ, or any I/O when you do streaming.
Round-tripping is slow due to how I/O and TCP work. On libzmq we can do about 20K messages/second using round-tripping, and 8M/sec using streaming. Streaming has additional optimizations like batching which you can't do with round-trip request-reply.
For a throughput performance test, send 10M messages from node 1 to node 2, then send back a single ACK when you get them. Time that on ZeroMQ and on JeroMQ, you should see around 3x difference in speed.
Please refer the throughput test between synchronous round-trip and asynchronous round-trip at
https://github.com/zeromq/jeromq/blob/master/src/test/java/guide/tripping.java
The asynchronous was x40 faster than the synchronous round-trip.
If you want to benchmark the full speed of jeromq, please run perf.LocalThr and perf.RemoteThr on your environment.

Is there anyway to know which user is calling the WCF Ria service on server side, using silverlight on clientside?

Is there anyway to know which user is calling the WCF Ria service on server side? Client side is siverlight, user has to be authenticated first in order to use the system.
I need to know which user is actually calling the service in my current task, thanks, i searched a lot, but seems no good findings.
Once the client side has successfully cleared your authentication challenge, the server can issue a token to the caller on the client side. In subsequent calls to the server, the client would send the token as one of the arguments and the server would verify the token and respond accordingly.
The token can contain a segment of information that identifies a given user, and implementing this will provide the functionality you are seeking.
The only guidelines for generating tokens is that they are unique, non-predictable and expirable. I have always encrypted my tokens so that they appear as gibberish, but step this is optional.
I've also done very much "googleing" and got a lot of headache before I got the solution.
I don't use RIA-Services - but it should be (hopefully) the same...:
The SL-Client sends a "login-request" to the server.
On the (WCF) server-side, I do the following (LoginData = Return-Info for SL-Client):
public LoginData LoginRequest() {
(...)
OperationContext context = OperationContext.Current;
System.ServiceModel.Channels.MessageProperties prp = context.IncomingMessageProperties;
System.ServiceModel.Channels.RemoteEndpointMessageProperty endPrp = prp[System.ServiceModel.Channels.RemoteEndpointMessageProperty.Name] as System.ServiceModel.Channels.RemoteEndpointMessageProperty;
(...)
try {
clientIP = endPrp.Address;
System.Net.IPAddress ipAddress = System.Net.IPAddress.Parse(clientIP);
System.Net.IPHostEntry ipHostEntry = System.Net.Dns.GetHostEntry(ipAddress);
(...)
If you want to check the users WindowsPrincipal, you can do the following (securityGroup = server-side setting, which users can login):
(...)
switch (securityGroup) {
case SecurityGroup.AllClientsCanAccess: {
clientCanLogin = true;
} break;
case SecurityGroup.UseWindowsCredentials: {
if (OperationContext.Current.ServiceSecurityContext != null && OperationContext.Current.ServiceSecurityContext.WindowsIdentity != null) {
if (OperationContext.Current.ServiceSecurityContext.WindowsIdentity.IsAuthenticated) {
if (subSecurityInfo1 == true) { // only clients in specific roles can log in
bool userRoleFound = false;
WindowsPrincipal userPrincipal = new WindowsPrincipal(OperationContext.Current.ServiceSecurityContext.WindowsIdentity);
if (userPrincipal == null)
break;
foreach (string userRoleToPass in subSecurityList) { // subSecurityList = settings, which roles can pass
loginError.ErrorInfo += string.Format("{0}\n", userRoleToPass);
if (userPrincipal.IsInRole(userRoleToPass)) {
clientCanLogin = userRoleFound = true;
break;
}
}
if (userRoleFound) {
loginError.ErrorInfo = string.Empty;
break;
}
else {
loginError.ErrorNo = LoginErrorCodeNoEnum.UserIsNotInRole;
}
}
(...)
Hope it helps...

Resources