I have a number of simple SIP endpoints that can be registered on a backend SIP registrars. They can be configured to be registred only on one of the call precessing engines.
I want to use Kamailio to relay REGISTER (and later INVITE) requests to the backend.
So far I have the following config
route[REGISTRAR] {
if (is_method("REGISTER")){
rewritehost("1.2.3.4");
xlog("Registering $(fu{uri.user}) with 1.2.3.4\n");
$var(frst) = "sip:" + $(fu{uri.user}) +"#1.2.3.4";
$var(scnd) = "sip:" + $(fu{uri.user}) +"#2.3.4.5";
uac_replace_from("$var(frst)");
uac_replace_to("$var(frst)");
if( !t_relay_to_tcp("1.2.3.4","5060") ) {
rewritehost("2.3.4.5");
uac_replace_from("$var(scnd)");
uac_replace_to("$var(scnd)");
xlog("Registering $(fu{uri.user}) with 2.3.4.5\n");
if( !t_relay_to_tcp("2.3.4.5","5060") ) {
sl_reply_error();
}
}
exit;
}
else return;
}
This route[REGISTRAR] is called from main SIP request routing. If 1.2.3.4 is UP my test endpoint registers and available for call from other endpoints (though I have to work with INVITE from test endpoint as well). But when 1.2.3.4 is down I get
ERROR: <core> [tcp_main.c:4249]: tcpconn_main_timeout(): connect 1.2.3.4:5060 failed (timeout)
in the /var/log/syslog. I thought that is t_relay_to_tcp fails I can repeat mangling of From and To headers and relay everything to 2.3.4.5, but this doesn't happen.
It might be because of the asyncronous nature of the transmission - kamailio scripts goes further while relayed tcp session is hanging in some backgroud thread.
How should I edit route[REGISTRAR] to relay to the 2.3.4.5 in case of tcp timeout?
Maybe the whole idea of relaying messages that way is wrong?
Some forums shows examples of registreing endpoints on kamailio itself, but it doesn't suit me. I believe that kamailio is powerful enough to solve my problem.
Looks like Kamailio doesn't work this way. So I changed my config like that:
route[REGISTRAR] {
if (is_method("REGISTER")){
rewritehost("1.2.3.4");
xlog("Registering $(fu{uri.user}) with 1.2.3.4\n");
$var(frst) = "sip:" + $(fu{uri.user}) +"#1.2.3.4";
uac_replace_from("$var(frst)");
uac_replace_to("$var(frst)");
t_on_failure("REGISTERBACKUP");
t_relay_to_tcp("1.2.3.4","5060");
}
else return;
failure_route[REGISTERBACKUP] {
rewritehost("2.3.4.5");
xlog("Registering $(fu{uri.user}) with 2.3.4.5\n");
#Edited to relay to 2.3.4.5
t_relay_to_tcp("2.3.4.5","5060");
}
When 1.2.3.4 is down my endpoint registers on 2.3.4.5. When 1.2.3.4 is up is of course registers on it.
Related
I'm using STM32 with ESp8266 using latest AT Command Firmware V2
Also i'm including https://github.com/nimaltd/ESP8266
Which helps parse at commands
I can connect to my router access point and my local tcp server but when sending GET requests i receive nothing on my local
const char* host = "192.168.1.9";
while(!Wifi_TcpIp_StartTcpConnection(0,host,3437,10)){
char buffer[] = "Unable to connect to TCP Backend\r\n";
HAL_UART_Transmit(&huart1,buffer,sizeof(buffer),HAL_MAX_DELAY);
};
uint8_t req ="GET /opaaa HTTP/1.1\r\n"; Wifi_TcpIp_SendDataTcp(0,sizeof(req),&req); //success but i receive nothing
Assuming the TCP communication works properly (you can connect to the server, send and receive data) and that the host you connect to serves HTTP on that port, the issue I can see with your request is that you're missing an additional CRLF at the end, like so:
char *req = "GET /opaaa HTTP/1.1\r\n\r\n";
Wifi_TcpIp_SendDataTcp(0, strlen(req), (uint8_t*)req);
This signifies the end of HTTP headers that you're sending. In your original case, the server may still be waiting for more headers and therefore holding with sending the response back to you.
I also suggest to clean up the sending code, one way of which I've pasted above - you were assigning a string to a single byte uint8_t variable.
I want to setup a datastreaming server in Processing, so the Client sends a String to the Server and the Server answeres it. For example Client - Server "Cupcake" then Server - Client "Cupcakce sounds funny" so the Server answeres the string. I tried this with the UDP library and opened the port on the server. But when the server had to answer the Clinet it did'nt work, because I can't open the client's ports. Any solutions?
Sounds like you need two-way communication.
Using UDP you would need two sketches that are both UDP servers and clients.
e.g.
sketch #1 listens on port 12000
sketch #1 sends data on port 12001
sketch #2 listens on port 12001
sketch #2 sends data on port 12000
You can also use TCP sockets.
As the Server you can use Examples > Libraries > Network > ChatServer
I'm surprised there's no ChatClient example, but you can get away with something like this:
import javax.swing.*;
import processing.net.*;
int port = 10002;
Client myClient;
void setup()
{
size(400, 400);
textFont(createFont("SanSerif", 16));
myClient = new Client(this, "localhost", port); // Starts a client on port 10002
background(0);
}
void draw()
{
background(0);
text("client - press ENTER to type\nconnected:"+myClient.active(), 15, 45);
}
void keyReleased() {
if (keyCode == ENTER) {
String message = JOptionPane.showInputDialog(null, "message: ", "TCP Client messaging", JOptionPane.QUESTION_MESSAGE);
println(message);
if (myClient.active() && message != null) {
myClient.write(message);
}
}
}
Note: The server must be running before the client so the client can connect.
Be sure to checkout the difference between UDP and TCP protocols to work out which one makes most sense to use in your case (especially if you pan to use more clients).
Another option worth looking into is WebSockets. This would allow you to have a WebSocket server in Processing and the client could either be another Processing sketch or simply any browser with WebSocket support(e.g. most modern)
I am trying to test an REST API on my local machine using frisby.js . It throws the following error.
Error: tunneling socket could not be established.
The machine address is something like 'https://machine_name:8443'
It seems that you are behind a proxy. Then, to make your frisby test working, you need to apply proxy configuration as follows:
var frisby = require('frisby');
frisby.globalSetup({
request: {
proxy: 'http://xx.xx.xx.xx:yyyy' // Provide proxy info (host, port) here
}
});
frisby.create('Your spec description here')
.get('https://machine_name:8443')
.expectStatus(200)
.toss();
Note also that you are using HTTPS protocol. Then you may find useful my answer in this post in case you have problems with SSL certificates
I'm currently starting a Tcl socket server like this:
socket -server Server 0
This lets the operating system pick an available port to start listening on. The question is that I don't want it to pick any port between 1025 and 64k, instead want to know if I can specify a range of ports? Something like this:
socket -server Server 40000-41000
And then the operating system would pick an available port between 40000 and 41000 for the server to listen on. Is there a way to do this? I can't find it in the Tcl API, but is there some nice API call way to do it rather than iterating through the port range until finding an available port?
The OS itself doesn't provide an API capable of doing that, and Tcl doesn't wrap one up for you as it is actually a pretty rare requirement. Conventionally, servers either listen on specific ports (so clients can know exactly what service to ask for; e.g., 21 for FTP, 22 for SSH, 25 for SMTP, 80 for HTTP, 161 for SNMP, 443 for HTTPS, 993 for secure IMAP) or the clients have some other way of being told what to ask for and genuinely any port will do (0 is the special “pick a card, any card” address). You can ask a Tcl server socket for what port it is actually using fconfigure:
set portNumber [lindex [fconfigure $socket -sockname] 2]
But to get a server socket on a port in a specific range? No API for that. We have to cook something ourselves:
for {set port 40000} {$port <= 41000} {incr port} {
if {![catch {
set sock [socket -server $yourHandler $port]
}]} then {
break
}
}
# If we failed...
if {![info exist sock]} {
error "No ports free in range 40k-41k"
}
This works because failing to bind the port will make the socket creation fail (neatly, catchably) and you can then try to bind the next port. It will take a while to scan over the port range, but it will work.
It's probably neater to wrap this up in a procedure. And Tcl 8.6's try construct will make the code a little less obscure:
proc portInRange {from to handler} {
for {set p $from} {$p <= $to} {incr p} {
try {
return [socket -server $handler $p]
} on error {} continue
}
error "No ports free in range $from-$to"
}
No, there's no API for that.
Generally servers listen on a specific port so that the clients can find the server. So such an API is not particularly useful.
Best to just write it yourself.
I have a simple Python server which can handle multiple clients:
import select
import socket
import sys
host = ''
port = 50000
backlog = 5
size = 1024
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host,port))
server.listen(backlog)
input = [server,sys.stdin]
running = 1
while running:
inputready,outputready,exceptready = select.select(input,[],[])
for s in inputready:
if s == server:
# handle the server socket
client, address = server.accept()
input.append(client)
elif s == sys.stdin:
# handle standard input
junk = sys.stdin.readline()
running = 0
else:
# handle all other sockets
data = s.recv(size)
if data:
s.send(data)
else:
s.close()
input.remove(s)
server.close()
One client connects to it and they can communicate. I have a third box from where I am sending a RST signal to the server (using Scapy). The TCP state diagram does not say if an endpoint is supposed to try to recover a connection when it sees a RESET. Is there any way I can force the server to recover the connection? (I want it to send back a SYN so that it gets connected to the third client)
Your question doesn't make much sense. TCP just doesn't work like that.
Re "The TCP state diagram does not say if an endpoint is supposed to try to recover a connection when it sees a RESET": RFC 793 #3.4 explicitly says "If the receiver was in any other state [than LISTEN or SYN-RECEIVED], it aborts the connection and advises the user and goes to the CLOSED state.".
An RST won't disturb a connection unless it arrives over that connection. I guess you could plausibly forge one, but you would have to know the current TCP sequence number, and you can't get that from within either of the peers, let alone a third host.
If you succeeded somehow, the connection would then be dead, finished, kaput. Can't see the point of that either.
I can't attach any meaning to your requirement for the server to send a SYN to the third host, in response to an RST from the third host, that has been made to appear as though it came from the second host. TCP just doesn't work anything like this either.
If you want the server to connect to the third host it will just have to call connect() like everybody else. In which case it becomes a client, of course.