I am currently handling a system that runs kamailio and asterisk in the same machine. The kamailio instances are being used to emulate multiple SIP domains, by means of From/To mangling of incoming packets, which are then routed to Asterisk. The attached
kamailio.cfg does this work.
There is an problem when handling SUBSCRIBE requests (as required for BLF and voicemail indications). My configuration is written so that these SUBSCRIBE requests are not handled by kamailio, but instead routed to asterisk. There is a failure to check
From/To headers to see whether NOTIFY packets generated as part of a subscription can be restored using the information in Record-Route. The end result is that kamailio ends up sending packets with garbled tags that are (rightly) rejected by the SIP endpoint.
The following is an example that demonstrates the issue (using Jitsi as endpoint):
After registration, Jitsi sends a SUBSCRIBE request:
SUBSCRIBE sip:avillacisIM@pbx.villacis.com SIP/2.0
Call-ID: 87ff107c2665316f4e257b358c54b3d4@0:0:0:0:0:0:0:0
CSeq: 2 SUBSCRIBE
From: "avillacisIM" <sip:avillacisIM@pbx.villacis.com>;tag=bf427f4a
To: "avillacisIM" <sip:avillacisIM@pbx.villacis.com>
Max-Forwards: 70
Contact: "avillacisIM" <sip:avillacisIM@192.168.3.2:5060;transport=udp;registering_acc=pbx_villacis_com>
User-Agent: Jitsi2.5.5255Linux
Event: message-summary
Accept: application/simple-message-summary
Expires: 3600
Via: SIP/2.0/UDP 192.168.3.2:5060;branch=z9hG4bK-343638-bd3ea073eb8920481b32962f3221eb6f
Proxy-Authorization: Digest username="avillacisIM",realm="pbx.villacis.com",nonce="U9lZJlPZV/r06Xep/ukc1UzAIO0V3TbS",uri="sip:avillacisIM@pbx.villacis.com",response="0e18f4913c2693f6154c91f158fb17fe"
Content-Length: 0
This packet is mangled by the configuration, and is sent to asterisk like this:
SUBSCRIBE sip:avillacisIM@pbx.villacis.com SIP/2.0
Record-Route: <sip:127.0.0.1;r2=on;lr=on;ftag=bf427f4a;vsf=AAAAAAAAAAAAAAAAAAAAHwAAAAAAAAAAAAAAAAAAAABAMTI3LjAuMC4xOjUwODA-;vst=AAAAAAAAAAAAAAAAAAAAHwAAAAAAAAAAAAAAAAAAAABAMTI3LjAuMC4xOjUwODA-;nat=yes>
Record-Route: <sip:192.168.2.18;r2=on;lr=on;ftag=bf427f4a;vsf=AAAAAAAAAAAAAAAAAAAAHwAAAAAAAAAAAAAAAAAAAABAMTI3LjAuMC4xOjUwODA-;vst=AAAAAAAAAAAAAAAAAAAAHwAAAAAAAAAAAAAAAAAAAABAMTI3LjAuMC4xOjUwODA-;nat=yes>
Call-ID: 87ff107c2665316f4e257b358c54b3d4@0:0:0:0:0:0:0:0
CSeq: 2 SUBSCRIBE
From: "avillacisIM" <sip:avillacisIM_pbx.villacis.com@127.0.0.1:5080>;tag=bf427f4a
To: "avillacisIM" <sip:avillacisIM_pbx.villacis.com@127.0.0.1:5080>
Max-Forwards: 69
Contact: "avillacisIM" <sip:avillacisIM@192.168.3.2:5060;transport=udp;registering_acc=pbx_villacis_com>
User-Agent: Jitsi2.5.5255Linux
Event: message-summary
Accept: application/simple-message-summary
Expires: 3600
Via: SIP/2.0/UDP 127.0.0.1;branch=z9hG4bKd941.2ab9cf36e41dc48855ae2cbe9a309d0a.0
Via: SIP/2.0/UDP 192.168.3.2:5060;rport=5060;branch=z9hG4bK-343638-bd3ea073eb8920481b32962f3221eb6f
Content-Length: 0
The asterisk response for the SUBSCRIBE:
SIP/2.0 200 OK
Via: SIP/2.0/UDP 127.0.0.1;branch=z9hG4bKd941.2ab9cf36e41dc48855ae2cbe9a309d0a.0;received=127.0.0.1;rport=5060
Via: SIP/2.0/UDP 192.168.3.2:5060;rport=5060;branch=z9hG4bK-343638-bd3ea073eb8920481b32962f3221eb6f
Record-Route: <sip:127.0.0.1;r2=on;lr=on;ftag=bf427f4a;vsf=AAAAAAAAAAAAAAAAAAAAHwAAAAAAAAAAAAAAAAAAAABAMTI3LjAuMC4xOjUwODA-;vst=AAAAAAAAAAAAAAAAAAAAHwAAAAAAAAAAAAAAAAAAAABAMTI3LjAuMC4xOjUwODA-;nat=yes>
Record-Route: <sip:192.168.2.18;r2=on;lr=on;ftag=bf427f4a;vsf=AAAAAAAAAAAAAAAAAAAAHwAAAAAAAAAAAAAAAAAAAABAMTI3LjAuMC4xOjUwODA-;vst=AAAAAAAAAAAAAAAAAAAAHwAAAAAAAAAAAAAAAAAAAABAMTI3LjAuMC4xOjUwODA-;nat=yes>
From: "avillacisIM" <sip:avillacisIM_pbx.villacis.com@127.0.0.1:5080>;tag=bf427f4a
To: "avillacisIM" <sip:avillacisIM_pbx.villacis.com@127.0.0.1:5080>;tag=as5562e95e
Call-ID: 87ff107c2665316f4e257b358c54b3d4@0:0:0:0:0:0:0:0
CSeq: 2 SUBSCRIBE
Server: Asterisk PBX 11.11.0
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE
Supported: replaces, timer
Expires: 3600
Contact: <sip:avillacisIM@127.0.0.1:5080>;expires=3600
Content-Length: 0
This is in turn transformed back by kamailio, and sent to Jitsi like this:
SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.3.2:5060;rport=5060;branch=z9hG4bK-343638-bd3ea073eb8920481b32962f3221eb6f
Record-Route: <sip:127.0.0.1;r2=on;lr=on;ftag=bf427f4a;vsf=AAAAAAAAAAAAAAAAAAAAHwAAAAAAAAAAAAAAAAAAAABAMTI3LjAuMC4xOjUwODA-;vst=AAAAAAAAAAAAAAAAAAAAHwAAAAAAAAAAAAAAAAAAAABAMTI3LjAuMC4xOjUwODA-;nat=yes>
Record-Route: <sip:192.168.2.18;r2=on;lr=on;ftag=bf427f4a;vsf=AAAAAAAAAAAAAAAAAAAAHwAAAAAAAAAAAAAAAAAAAABAMTI3LjAuMC4xOjUwODA-;vst=AAAAAAAAAAAAAAAAAAAAHwAAAAAAAAAAAAAAAAAAAABAMTI3LjAuMC4xOjUwODA-;nat=yes>
From: "avillacisIM" <sip:avillacisIM@pbx.villacis.com>;tag=bf427f4a
To: "avillacisIM" <sip:avillacisIM@pbx.villacis.com>;tag=as5562e95e
Call-ID: 87ff107c2665316f4e257b358c54b3d4@0:0:0:0:0:0:0:0
CSeq: 2 SUBSCRIBE
Server: Asterisk PBX 11.11.0
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE
Supported: replaces, timer
Expires: 3600
Contact: <sip:avillacisIM@127.0.0.1:5080;alias=127.0.0.1~5080~1>;expires=3600
Content-Length: 0
Now asterisk wants to send a NOTIFY to the endpoint for the subscription. The NOTIFY looks like this:
NOTIFY sip:avillacisIM@192.168.3.2:5060;transport=udp;registering_acc=pbx_villacis_com SIP/2.0
Via: SIP/2.0/UDP 127.0.0.1:5080;branch=z9hG4bK658fa5fc;rport
Max-Forwards: 70
Route:
<sip:127.0.0.1;r2=on;lr=on;ftag=bf427f4a;vsf=AAAAAAAAAAAAAAAAAAAAHwAAAAAAAAAAAAAAAAAAAABAMTI3LjAuMC4xOjUwODA-;vst=AAAAAAAAAAAAAAAAAAAAHwAAAAAAAAAAAAAAAAAAAABAMTI3LjAuMC4xOjUwODA-;nat=yes>,<sip:192.168.2.18;r2=on;lr=on;ftag=bf427f4a;vsf=AAAAAAAAAAAAAAAAAAAAHwAAAAAAAAAAAAAAAAAAAABAMTI3LjAuMC4xOjUwODA-;vst=AAAAAAAAAAAAAAAAAAAAHwAAAAAAAAAAAAAAAAAAAABAMTI3LjAuMC4xOjUwODA-;nat=yes>
From: "asterisk" <sip:asterisk@127.0.0.1:5080>;tag=as5562e95e
To: <sip:avillacisIM@192.168.3.2:5060;transport=udp;registering_acc=pbx_villacis_com>;tag=bf427f4a
Contact: <sip:asterisk@127.0.0.1:5080>
Call-ID: 87ff107c2665316f4e257b358c54b3d4@0:0:0:0:0:0:0:0
CSeq: 102 NOTIFY
User-Agent: Asterisk PBX 11.11.0
Event: message-summary
Content-Type: application/simple-message-summary
Subscription-State: active
Content-Length: 89
Messages-Waiting: no
Message-Account: sip:*97@127.0.0.1:5080
Voice-Message: 0/0 (0/0)
Here is where the bug appears. The autoprocessing does not recognize that the From header (From: "asterisk" <sip:asterisk@127.0.0.1:5080>;tag=as5562e95e) from the above request has nothing to do with the saved information (vsf parameter). Instead, it
blindly mangles the From header, and does not even run a sanity check on the result before routing it. The end result is shown below.
NOTIFY sip:avillacisIM@192.168.3.2:5060;transport=udp;registering_acc=pbx_villacis_com SIP/2.0
Record-Route: <sip:192.168.2.18;r2=on;lr=on;ftag=as5562e95e>
Record-Route: <sip:127.0.0.1;r2=on;lr=on;ftag=as5562e95e>
Via: SIP/2.0/UDP 192.168.2.18;branch=z9hG4bK8333.8bfe7bc2bd554a8631f0d00d463b28ee.0
Via: SIP/2.0/UDP 127.0.0.1:5080;branch=z9hG4bK658fa5fc;rport=5080
Max-Forwards: 69
From: "asterisk" <sip:asterisk@12(.0.0.1:5080.....@127.0.0.1:5080>;tag=as5562e95e
To: <sip:avillacisIM@192.168.3.2:5060;transport=udp;registering_acc=pbx_villacis_com>;tag=bf427f4a
Contact: <sip:asterisk@127.0.0.1:5080>
Call-ID: 87ff107c2665316f4e257b358c54b3d4@0:0:0:0:0:0:0:0
CSeq: 102 NOTIFY
User-Agent: Asterisk PBX 11.11.0
Event: message-summary
Content-Type: application/simple-message-summary
Subscription-State: active
Content-Length: 89
Messages-Waiting: no
Message-Account: sip:*97@127.0.0.1:5080
Voice-Message: 0/0 (0/0)
From examination of the source code, the vsf and vst strings are base64 encodings of the result of XORing the byte strings of the old and new tags. For this to work, the headers of future packets should match. However, here kamailio does not realize that
the header does not match (by the ftag), and also does not check that the resulting "restored" header is a valid header.
Hello all,
I've had proposed a fix to SCA module in the tracker (
https://sip-router.org/tracker/index.php?do=details&task_id=446) but did´t
hear anything about it until now.
I would appreciate some comments on that to see if its feasible to be
committed or even hear for anyone else using SCA module with Polycom phones
to see if they have the same issue described.
Thanks,
João Vitor Arruda
Hi, I am developing a social application where I want to enable voice & video calling function and still I don't know what to use in server side, do you have any product that I can use to develop the server side(for 10.000+ users)?
Thank you in advance.
I am trying to track down a memory leak that was triggered by a patch I wrote for my local copy of kamailio 4.1.4 . For this, I am following the documentation at http://www.kamailio.org/dokuwiki/doku.php/troubleshooting:memory . This page claims that once
memlog is set in the configuration file, a kamailio process will dump a report of the allocation map when shutting down, or when receiving a SIGUSR1. I have configured my kamailio.cfg with memlog=1 and no other change, and I see the memory report on
shutdown for all processes. However, when I send a SIGUSR1 to a kamailio process, the process does absolutely nothing, with the exception of the first kamailio process (the one reported as Type=attendant by "kamctl ps"). All of the other processes just
ignore SIGUSR1. What is going on? It is inconvenient to force a shutdown of all the kamailio processes just to get the memory report.
My kamailio.cfg configuration file is attached.
I am having trouble using SIP.js (http://sipjs.com/) to handle a SUBSCRIBE for presence information. With Jitsi clients (using plain UDP), presence seems to work correctly. However, when using SIP.js via a websocket, Kamailio is unable to send the NOTIFY
for the presence event. However, MESSAGE packets are routed correctly between peers, even through websockets.
The location table after registration looks like this:
+-----+----------------------+----------+------------------+--------------------------------------+------------------------------------+------+---------------------+-------+------------------------+------+---------------------+-------+--------+--------------+-----------------------+---------+-------------------------------------------------+--------+
| id | ruid | username | domain | contact | received | path | expires | q | callid | cseq | last_modified | flags | cflags |
user_agent | socket | methods | instance | reg_id |
+-----+----------------------+----------+------------------+--------------------------------------+------------------------------------+------+---------------------+-------+------------------------+------+---------------------+-------+--------+--------------+-----------------------+---------+-------------------------------------------------+--------+
| 192 | uloc-53d96398-1afc-1 | admin | pbx.villacis.com | sip:nfinhooe@192.0.2.90;transport=ws | sip:192.168.3.2:41478;transport=WS | NULL | 2014-07-30 17:18:57 | -1.00 | 6a2dot9ihoobhng9ackqmq | 90 | 2014-07-30 17:08:57 | 0 | 64 |
SIP.js/0.5.0 | tls:192.168.2.18:5061 | 782 | <urn:uuid:b8888e95-7833-46a4-a21e-8d2e809a66b8> | 1 |
+-----+----------------------+----------+------------------+--------------------------------------+------------------------------------+------+---------------------+-------+------------------------+------+---------------------+-------+--------+--------------+-----------------------+---------+-------------------------------------------------+--------+
When running the following javascript code:
var subs = ua.subscribe('admin(a)pbx.villacis.com', 'presence');
subs.on('notify', function (n) { alert(n.request.body); });
... I see the following traffic in the browser console area:
SUBSCRIBE sip:admin@pbx.villacis.com SIP/2.0
Via: SIP/2.0/WSS 192.0.2.90;branch=z9hG4bK3654279
Max-Forwards: 70
To: <sip:admin@pbx.villacis.com>
From: "Administrator" <sip:admin@pbx.villacis.com>;tag=rt0men9qve
Call-ID: pa7jno8q3op5pu0qitad
CSeq: 322 SUBSCRIBE
Proxy-Authorization: Digest algorithm=MD5, username="admin", realm="pbx.villacis.com", nonce="U9lswVPZa5WSu5jz1P/jIOJTvthKXw6v", uri="sip:admin@pbx.villacis.com", response="f7246e64573b5888d69896a70d4204aa"
Event: presence
Expires: 3600
Contact: <sip:nfinhooe@192.0.2.90;transport=ws>
Allow: ACK,CANCEL,BYE,OPTIONS,MESSAGE
Supported: outbound
User-Agent: SIP.js/0.5.0
Content-Length: 0
SIP/2.0 202 OK
Via: SIP/2.0/WSS 192.0.2.90;branch=z9hG4bK3654279;rport=41478;received=192.168.3.2
To: <sip:admin@pbx.villacis.com>;tag=a6a1c5f60faecf035a1ae5b6e96e979a-84c3
From: "Administrator" <sip:admin@pbx.villacis.com>;tag=rt0men9qve
Call-ID: pa7jno8q3op5pu0qitad
CSeq: 322 SUBSCRIBE
Expires: 3600
Contact: <sip:192.168.2.18:5061;transport=ws>
Server: kamailio (4.1.4 (x86_64/linux))
Content-Length: 0
However, I also get the following messages in the kamailio log:
Jul 30 17:03:01 elx3 /usr/sbin/kamailio[6908]: WARNING: <core> [msg_translator.c:2506]: via_builder(): TCP/TLS connection (id: 0) for WebSocket could not be found
Jul 30 17:03:01 elx3 /usr/sbin/kamailio[6908]: ERROR: tm [t_msgbuilder.c:1365]: assemble_via(): assemble_via: via building failed
Jul 30 17:03:01 elx3 /usr/sbin/kamailio[6908]: ERROR: tm [t_msgbuilder.c:1544]: build_uac_req(): build_uac_req(): Error while assembling Via
Jul 30 17:03:01 elx3 /usr/sbin/kamailio[6908]: ERROR: tm [uac.c:338]: t_uac_prepare(): t_uac: Error while building message
Jul 30 17:03:01 elx3 /usr/sbin/kamailio[6908]: ERROR: presence [notify.c:1591]: send_notify_request(): in function tmb.t_request_within
Jul 30 17:03:01 elx3 /usr/sbin/kamailio[6908]: ERROR: presence [notify.c:1678]: notify(): sending Notify not successful
Jul 30 17:03:01 elx3 /usr/sbin/kamailio[6908]: ERROR: presence [subscribe.c:678]: update_subscription(): Could not send notify
Jul 30 17:03:01 elx3 /usr/sbin/kamailio[6908]: ERROR: presence [subscribe.c:713]: update_subscription(): occured
Jul 30 17:03:01 elx3 /usr/sbin/kamailio[6908]: ERROR: presence [subscribe.c:994]: handle_subscribe(): in update_subscription
I have found a discussion at http://marc.info/?l=sr-users&m=136624316816288&w=2 which recommends fix_nated_contact(), but I am not really sure about how to add it, or what conditions to check on whether it should be used. I added the call to
fix_nated_contact() like this:
# Caller NAT detection route
route[NATDETECT] {
#!ifdef WITH_NAT
force_rport();
#
# 1 - Contact header field is searched for occurrence of RFC1918 or rfc6598 addresses.
# 2 - the "received" test is used: address in Via is compared against source IP address of signaling
# 16 - test if the source port is different from the port in Via
# 64 - test if the source connection of signaling is a WebSocket
# -----
# 83
#!ifdef WITH_WEBSOCKET
# Do NAT traversal stuff for requests from a WebSocket
# connection - even if it is not behind a NAT!
# This won't be needed in the future if Kamailio and the
# WebSocket client support Outbound and Path.
if (nat_uac_test("83")) {
#!else
if (nat_uac_test("19")) {
#!endif
if (is_method("REGISTER")) {
fix_nated_register();
#!ifdef WITH_WEBSOCKET
if (nat_uac_test("64")) fix_nated_contact();
#!endif
} else {
if (is_first_hop())
if (!add_contact_alias()) {
xlog("L_ERR", "Error aliasing contact <$ct>\n");
sl_send_reply("400", "Bad Request");
exit;
}
}
setflag(FLT_NATS);
}
#!endif
return;
}
After registration, "kamctl ul show" reports this:
[root@elx3 js]# kamctl ul show
Domain:: location table=512 records=1 max_slot=1
AOR:: admin(a)pbx.villacis.com
Contact:: sip:85017jar@192.168.3.2:41777;transport=ws Q=
Expires:: 584
Callid:: argl25kg0r4qe8lbtbhn9f
Cseq:: 82
User-agent:: SIP.js/0.5.0
Received:: sip:192.168.3.2:41777;transport=WS
State:: CS_NEW
Flags:: 0
Cflag:: 64
Socket:: tls:192.168.2.18:5061
Methods:: 782
Ruid:: uloc-53d971c7-297f-1
Instance:: <urn:uuid:75464840-96b8-4e22-8eaa-5012ba327086>
Reg-Id:: 1
Last-Keepalive:: 1406759390
Last-Modified:: 1406759390
However, it still does not work:
Jul 30 17:30:21 elx3 /usr/sbin/kamailio[10624]: WARNING: <core> [msg_translator.c:2506]: via_builder(): TCP/TLS connection (id: 0) for WebSocket could not be found
Jul 30 17:30:21 elx3 /usr/sbin/kamailio[10624]: ERROR: tm [t_msgbuilder.c:1365]: assemble_via(): assemble_via: via building failed
Jul 30 17:30:21 elx3 /usr/sbin/kamailio[10624]: ERROR: tm [t_msgbuilder.c:1544]: build_uac_req(): build_uac_req(): Error while assembling Via
Jul 30 17:30:21 elx3 /usr/sbin/kamailio[10624]: ERROR: tm [uac.c:338]: t_uac_prepare(): t_uac: Error while building message
Jul 30 17:30:21 elx3 /usr/sbin/kamailio[10624]: ERROR: presence [notify.c:1591]: send_notify_request(): in function tmb.t_request_within
Jul 30 17:30:21 elx3 /usr/sbin/kamailio[10624]: ERROR: presence [notify.c:1678]: notify(): sending Notify not successful
Jul 30 17:30:21 elx3 /usr/sbin/kamailio[10624]: ERROR: presence [subscribe.c:678]: update_subscription(): Could not send notify
Jul 30 17:30:21 elx3 /usr/sbin/kamailio[10624]: ERROR: presence [subscribe.c:713]: update_subscription(): occured
Jul 30 17:30:21 elx3 /usr/sbin/kamailio[10624]: ERROR: presence [subscribe.c:994]: handle_subscribe(): in update_subscription
Hi,
As the mobile voip is getting more and more popular these days, there has
been a strong opposition from GSM operators against mobile voip apps. They
often use tactics like blocking voip ports, or detect and block voip
traffic and in some cases restricting udp traffic altogether to very low
upload and download speeds. See below link for some details,
http://www.linphone.org/eng/blog/linphone-over-3g.html
While not all the problems can be solved right now (especially the limiting
udp traffic, since RTP always uses udp transport) I was wondering if we can
at least handle the sip related problems. The most important of them is SIP
traffic detection. While some forks would suggest using TCP/TLS to encrypt
SIP traffic, it has a few problems, e.g.
1. It requires somewhat high resources on mobile devices, so many low-end
android phones simply can't use it.
2. There is possibility that encryption signature may identify it as SIP
traffic. There exists firewalls (often deployed in middle eastern
countries) which have huge database of encryption signatures and patterns
which although may not decrypt the sip packet but at least identify it as
sip packet and block it.
Also with rough agencies of evil empires spying over millions of users
worldwide makes the current encryption standards pretty much pointless, at
least in terms of user privacy and network security. So there is a strong
need to experiment with new ideas and concepts to regain internet freedom.
Some of such ideas are,
1. Convert sip traffic which is plain text to binary format just before
transmitting it and revert it to plain text upon reception.
2. XOR the sip traffic (pretty much same as binary sip).
3. Use some very lightweight but effective / non-standard encryption
algorithm, e.g.
https://github.com/mshary/itv
All these ideas require that SIP server such as Kamailio is able to adopt
to these, preferably with minimal or no change in native code. The NoSIP
module seems an interesting module in this regard. It provides all traffic
it thinks is not the SIP traffic to configuration script, where we can do
our own parsing and do whatever we want with it. I have two questions about
this,
1. If parsed message is SIP, we can we send it back to kamailio core to get
it processed as if it is a normal SIP message received by kamailio?
2. Can this module or any other module available in kamailio, that can
provide us full sip packet that is about to be transmitted over sip socket,
so we can "encode" it just before it is sent to next hop?
I know this would be like writing a SIP transport in kamailio script which
would be very tough if not impossible to implement in native core. But it
will really help in winning the modern mobile voip challenges.
Thank you.
Sir pl help for registration of soft phone to my local sip server my email
vijay8538(a)gmail.com
---
This email is free from viruses and malware because avast! Antivirus protection is active.
http://www.avast.com
Greetings,
We have had good success in the past using rtpproxy with internal and
external interfaces however, we are attempting to migrate to rtpengine
now but are running into an issue (apparently this feature is not
supported).
So, my question is as follows, does this mean we need to multiple
rtpengine and bind them to each interface? Additionally, in this
setup can audio be bridged between the 2 rtpengine processes?
If not, how do people over come this difference?
--
Paul Belanger | PolyBeacon, Inc.
Jabber: paul.belanger(a)polybeacon.com | IRC: pabelanger (Freenode)
Github: https://github.com/pabelanger | Twitter: https://twitter.com/pabelanger
Hi,
I want to do LCR based on from uri. I get I need to do regular expression
matching but have no idea where to look to start.
Any pointers would be good.
Thanks
Keith