I'm using the Sdp class from the Microsoft.Rtc.Signaling namespace.
Now I want to parse the following Sdp-Text:
v=0
o=- 0 0 IN IP4 192.168.253.202
s=session
c=IN IP4 239.168.253.202
t=0 0
m=message 5060 sip null
a=accept-types:text/plain
using the following code:
var text = #"v=0
o=- 0 0 IN IP4 192.168.253.202
s=session
c=IN IP4 239.168.253.202
t=0 0
m=message 5060 sip null
a=accept-types:text/plain
";
Sdp<SdpGlobalDescription, SdpMediaDescription> sessionDescription2 = new Sdp<SdpGlobalDescription, SdpMediaDescription>();
var encodedText = Encoding.ASCII.GetBytes(text);
if (sessionDescription2.TryParse(encodedText, 0, encodedText.Length, false))
{
sessionDescription2.Dump();
IList<SdpMediaDescription> activeMediaTypes = sessionDescription2.MediaDescriptions;
foreach (var sdpMediaDescription in activeMediaTypes)
{
sdpMediaDescription.Dump();
foreach (var sdpBandwidth in sdpMediaDescription.Bandwidths)
{
sdpBandwidth.Dump();
}
foreach (var sdpAttribute in sdpMediaDescription.Attributes)
{
sdpAttribute.Dump();
}
}
}
else
{
sessionDescription2.LastParseErrorMessage.Dump();
sessionDescription2.LastParseErrorLineNumber.Dump();
}
Console.ReadLine();
.Dump() is from nuget ConsoleDump Package.
All information is parsed but the 'c' connection is set to null.
Any hint?
That was easy.
I must look in sessionDescription2.GlobalDescription - there it is!
Related
I found an example here but I keep getting the following error, I have tried various combinations in the header to no avail... Postman requests work fine. I am missing something... This is a 443 port... Do I need to use another method? As you will discover reading on I am not familiar with making HTTPS requests but need to add this to my software to pull recent data from a server. Any assistance would be appreciated...
HTTP/1.1 400 Bad Request
Server: awselb/2.0
Date: Mon, 25 May 2020 16:52:31 GMT
Content-Type: text/html
Content-Length: 236
Connection: close
#include <windows.h>
#include <string>
#include <stdio.h>
#include <winsock2.h>
#include <WS2tcpip.h>
#include <windows.h>
#include <iostream>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
using std::string;
...
// Initialize Dependencies to the Windows Socket.
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
fprintf(fpSessionLog,"WSAStartup failed.\n");
fflush(fpSessionLog);
goto SKIP;
}
// We first prepare some "hints" for the "getaddrinfo" function
// to tell it, that we are looking for a IPv4 TCP Connection.
struct addrinfo hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET; // We are targeting IPv4
hints.ai_protocol = IPPROTO_TCP; // We are targeting TCP
hints.ai_socktype = SOCK_STREAM; // We are targeting TCP so its SOCK_STREAM
// Aquiring of the IPv4 address of a host using the newer
// "getaddrinfo" function which outdated "gethostbyname".
// It will search for IPv4 addresses using the TCP-Protocol.
struct addrinfo* targetAdressInfo = NULL;
DWORD getAddrRes = getaddrinfo("api-thisSite.com", NULL, &hints, &targetAdressInfo);
if (getAddrRes != 0 || targetAdressInfo == NULL)
{
fprintf(fpSessionLog,"Could not resolve the Host Name\n");
fflush(fpSessionLog);
WSACleanup();
goto SKIP;
}
// Create the Socket Address Informations, using IPv4
// We dont have to take care of sin_zero, it is only used to extend the length of SOCKADDR_IN to the size of SOCKADDR
SOCKADDR_IN sockAddr;
sockAddr.sin_addr = ((struct sockaddr_in*) targetAdressInfo->ai_addr)->sin_addr; // The IPv4 Address from the Address Resolution Result
sockAddr.sin_family = AF_INET; // IPv4
sockAddr.sin_port = htons(443);
// We have to free the Address-Information from getaddrinfo again
freeaddrinfo(targetAdressInfo);
// Creation of a socket for the communication with the Web Server,
// using IPv4 and the TCP-Protocol
SOCKET webSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (webSocket == INVALID_SOCKET)
{
fprintf(fpSessionLog,"Creation of the Socket Failed\n");
fflush(fpSessionLog);
WSACleanup();
goto SKIP;
}
// Establishing a connection to the web Socket
//cout << "Connecting...\n";
fprintf(fpSessionLog,"Connecting...\n");
fflush(fpSessionLog);
if(connect(webSocket, (SOCKADDR*)&sockAddr, sizeof(sockAddr)) != 0)
{
fprintf(fpSessionLog,"Could not connect!\n");
fflush(fpSessionLog);
closesocket(webSocket);
WSACleanup();
goto SKIP;
}
fprintf(fpSessionLog,"Connected!\n");
fflush(fpSessionLog);
// Sending a HTTP-GET-Request to the Web Server
const char* httpRequest = "GET /api/v1/ecm HTTP/1.1\r\nHost: api-thisSite.com\r\nX-Authorization: {api key goes here}\r\nAccept: application/json"
fprintf(fpSessionLog,"Formulated Server Request: %s \n",httpRequest);
fflush(fpSessionLog);
int sentBytes = send(webSocket, httpRequest, strlen(httpRequest),0);
if (sentBytes < strlen(httpRequest) || sentBytes == SOCKET_ERROR)
{
//cout << "Could not send the request to the Server" << endl;
//system("pause");
fprintf(fpSessionLog,"Could not send the request to the Server!\n");
fflush(fpSessionLog);
closesocket(webSocket);
WSACleanup();
goto SKIP;
}
// Receiving and Displaying an answer from the Web Server
char buffer[10000];
ZeroMemory(buffer, sizeof(buffer));
int dataLen;
while ((dataLen = recv(webSocket, buffer, sizeof(buffer), 0) > 0))
{
int i = 0;
while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') {
//cout << buffer[i];
fprintf(fpSessionLog,"%c",buffer[i]);
i += 1;
}
}
fflush(fpSessionLog);
// Cleaning up Windows Socket Dependencies
closesocket(webSocket);
WSACleanup();
SKIP:
HTTP/1.1 400 Bad Request
Server: awselb/2.0
Date: Mon, 25 May 2020 20:32:40 GMT
Content-Type: text/html
Content-Length: 236
Connection: close
<html>
<head><title>400 The plain HTTP request was sent to HTTPS port</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<center>The plain HTTP request was sent to HTTPS port</center>
</body>
</html>
How do I send an HTTPS request to an HTTPS port?
I'm working with PubNub. I have a standard WebRTC string being published with PubNub.
self.pubnub.publish(channel: self.channels[0], message: ["type": "offer", "sdp": sessionDesc.sdp]) { result in
Then the PubNub Listener listens to the Published signals on the Channel.
let listener = SubscriptionListener(queue: .main)
listener.didReceiveMessage = { message in
print("[Did Receive Message]: \(message)")
}
pubnub.add(listener)
pubnub.subscribe(to: channels, withPresence: true)
That works just fine, I get my SDP strings.
[Did Receive Message]: User 'pn-4D77E0B5-0145-ACAC-0366CB301ABC' sent '{"type":"offer","sdp":"v=0\r\no=- 4836309355638585269 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE audio video\r\na=msid-semantic: WMS ARDAMS\r\nm=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 102 0 8 106 105 13 110 112 113 126\r\nc=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=ice-ufrag:tKqW\r\na=ice-pwd:KNDM86R+JqsLqupw3J288kmJ\r\na=ice-options:trickle renomination\r\na=fingerprint:sha-256.....
My problem is that from within 'message'. How do I capture the 'type' and 'sdp' strings???
listener.didReceiveMessage = { message in
print("[Did Receive Message]: \(message)")
var type = message["type"] as? String <---- this does not work.
}
Thank you
Quoting form this online kernel doc
SO_TIMESTAMPING
Generates timestamps on reception, transmission or both. Supports
multiple timestamp sources, including hardware. Supports generating
timestamps for stream sockets.
Linux supports TCP timestamping, and I tried to write some demo code to get any timestamp for TCP packet.
The server code as below:
//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
perror("bind failed. Error");
return 1;
}
puts("bind done");
//Listen
listen(socket_desc , 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
int c = sizeof(struct sockaddr_in);
client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c);
if (client_sock < 0)
{
perror("accept failed");
return 1;
}
// Note: I am trying to get software timestamp only here..
int oval = SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE;
int olen = sizeof( oval );
if ( setsockopt( client_sock, SOL_SOCKET, SO_TIMESTAMPING, &oval, olen ) < 0 )
{ perror( "setsockopt TIMESTAMP"); exit(1); }
puts("Connection accepted");
char buf[] = "----------------------------------------";
int len = strlen( buf );
struct iovec myiov[1] = { {buf, len } };
unsigned char cbuf[ 40 ] = { 0 };
int clen = sizeof( cbuf );
struct msghdr mymsghdr = { 0 };
mymsghdr.msg_name = NULL;
mymsghdr.msg_namelen = 0;
mymsghdr.msg_iov = myiov;
mymsghdr.msg_iovlen = 1;
mymsghdr.msg_control = cbuf;
mymsghdr.msg_controllen = clen;
mymsghdr.msg_flags = 0;
int read_size = recvmsg( client_sock, &mymsghdr, 0);
if(read_size == 0)
{
puts("Client disconnected");
fflush(stdout);
}
else if(read_size == -1)
{
perror("recv failed");
}
else
{
struct msghdr *msgp = &mymsghdr;
printf("msg received: %s \n",(char*)msgp->msg_iov[0].iov_base);// This line is successfully hit.
// Additional info: print msgp->msg_controllen inside gdb is 0.
struct cmsghdr *cmsg;
for ( cmsg = CMSG_FIRSTHDR( msgp );
cmsg != NULL;
cmsg = CMSG_NXTHDR( msgp, cmsg ) )
{
printf("Time GOT!\n"); // <-- This line is not hit.
if (( cmsg->cmsg_level == SOL_SOCKET )
&&( cmsg->cmsg_type == SO_TIMESTAMPING ))
printf("TIME GOT2\n");// <-- of course , this line is not hit
}
}
Any ideas why no timestamping is available here ? Thanks
Solution
I am able to get the software timestamp along with hardware timestamp using onload with solarflare NIC.
Still no idea how to get software timestamp alone.
The link you gave, in the comments at the end, says:
I've discovered why it doesn't work. SIOCGSTAMP only works for UDP
packets or RAW sockets, but does not work for TCP. – Gio Mar 17 '16 at 9:331
it doesn't make sense to ask for timestamps for TCP, because there's
no direct correlation between arriving packets and data becoming
available. If you really want timestamps for TCP you'll have to use
RAW sockets and implement your own TCP stack (or use a userspace TCP
library). – ecatmur Jul 4 '16 at 10:39
I'm trying to authenticate Radius Requests against Restful API. My Virtual Server configuration as below:
authorize {
filter_username
filter_password
preprocess
auth_log
if (User-Password) {
update control {
Auth-Type := rest
}
}
}
authenticate {
rest
}
My radius -X output is:
(0) Received Access-Request Id 202 from 127.0.0.2:10708 to 127.0.0.2:1812 length 73
(0) User-Name = "bob"
(0) User-Password = "hello"
(0) NAS-IP-Address = 127.0.0.2
(0) NAS-Port = 1
(0) Message-Authenticator = 0xcd622e98255234964d081be2513a0a9c
(0) # Executing section authorize from file /usr/local/etc/raddb/sites-enabled/testserver
(0) authorize {
(0) policy filter_username {
(0) if (&User-Name) {
(0) if (&User-Name) -> TRUE
(0) if (&User-Name) {
(0) if (&User-Name =~ / /) {
(0) if (&User-Name =~ / /) -> FALSE
(0) if (&User-Name =~ /#[^#]*#/ ) {
(0) if (&User-Name =~ /#[^#]*#/ ) -> FALSE
(0) if (&User-Name =~ /\.\./ ) {
(0) if (&User-Name =~ /\.\./ ) -> FALSE
(0) if ((&User-Name =~ /#/) && (&User-Name !~ /#(.+)\.(.+)$/)) {
(0) if ((&User-Name =~ /#/) && (&User-Name !~ /#(.+)\.(.+)$/)) -> FALSE
(0) if (&User-Name =~ /\.$/) {
(0) if (&User-Name =~ /\.$/) -> FALSE
(0) if (&User-Name =~ /#\./) {
(0) if (&User-Name =~ /#\./) -> FALSE
(0) } # if (&User-Name) = notfound
(0) } # policy filter_username = notfound
(0) policy filter_password {
(0) if (&User-Password && (&User-Password != "%{string:User-Password}")) {
(0) EXPAND %{string:User-Password}
(0) --> hello
(0) if (&User-Password && (&User-Password != "%{string:User-Password}")) -> FALSE
(0) } # policy filter_password = notfound
(0) [preprocess] = ok
(0) auth_log: EXPAND /antikor/log/radacct/%{%{Packet-Src-IP-Address}:-%{Packet-Src-IPv6-Address}}/auth-detail-%Y%m%d
(0) auth_log: --> /antikor/log/radacct/127.0.0.2/auth-detail-20170429
(0) auth_log: /antikor/log/radacct/%{%{Packet-Src-IP-Address}:-%{Packet-Src-IPv6-Address}}/auth-detail-%Y%m%d expands to /antikor/log/radacct/127.0.0.2/auth-detail-20170429
(0) auth_log: EXPAND %t
(0) auth_log: --> Sat Apr 29 19:46:26 2017
(0) [auth_log] = ok
(0) if (User-Password) {
(0) if (User-Password) -> TRUE
(0) if (User-Password) {
(0) update control {
(0) Auth-Type := rest
(0) } # update control = noop
(0) } # if (User-Password) = noop
(0) } # authorize = ok
(0) Found Auth-Type = rest
(0) # Executing group from file /usr/local/etc/raddb/sites-enabled/testserver
(0) authenticate {
rlm_rest (rest): Reserved connection (0)
(0) rest: Expanding URI components
(0) rest: EXPAND http://127.0.0.1:8902
(0) rest: --> http://127.0.0.1:8902
(0) rest: EXPAND /test.php?action=authenticate
(0) rest: --> /test.php?action=authenticate
(0) rest: Sending HTTP POST to "http://127.0.0.1:8902/test.php?action=authenticate"
(0) rest: EXPAND {"username":"%{User-Name}", "password":"%{User-Password}"}
(0) rest: --> {"username":"bob", "password":"hello"}
(0) rest: Processing response header
(0) rest: Status : 200 (OK)
(0) rest: Type : json (application/json)
(0) rest: Parsing attribute "control:Cleartext-Password"
(0) rest: EXPAND hello
(0) rest: --> hello
(0) rest: Cleartext-Password := "hello"
(0) rest: Parsing attribute "request:User-Password"
(0) rest: EXPAND hello
(0) rest: --> hello
(0) rest: User-Password := "hello"
(0) rest: Parsing attribute "reply:Reply-Message"
(0) rest: EXPAND Hello bob
(0) rest: --> Hello bob
(0) rest: Reply-Message := "Hello bob"
rlm_rest (rest): Released connection (0)
Need 5 more connections to reach 10 spares
rlm_rest (rest): Opening additional connection (5), 1 of 27 pending slots used
rlm_rest (rest): Connecting to "http://127.0.0.1:8902/test.php"
(0) [rest] = updated
(0) } # authenticate = updated
(0) Failed to authenticate the user
(0) Login incorrect: [bob/hello] (from client antikor-l2tp port 1)
(0) Using Post-Auth-Type Reject
(0) # Executing group from file /usr/local/etc/raddb/sites-enabled/testserver
(0) Post-Auth-Type REJECT {
(0) attr_filter.access_reject: EXPAND %{User-Name}
(0) attr_filter.access_reject: --> bob
(0) attr_filter.access_reject: Matched entry DEFAULT at line 11
(0) [attr_filter.access_reject] = updated
(0) [eap] = noop
(0) policy remove_reply_message_if_eap {
(0) if (&reply:EAP-Message && &reply:Reply-Message) {
(0) if (&reply:EAP-Message && &reply:Reply-Message) -> FALSE
(0) else {
(0) [noop] = noop
(0) } # else = noop
(0) } # policy remove_reply_message_if_eap = noop
(0) } # Post-Auth-Type REJECT = updated
(0) Delaying response for 1.000000 seconds
Waking up in 0.3 seconds.
Waking up in 0.6 seconds.
(0) Sending delayed response
(0) Sent Access-Reject Id 202 from 127.0.0.2:1812 to 127.0.0.2:10708 length 33
(0) Reply-Message = "Hello bob"
I added both control:Cleartext-Password and request:User-Password variables to test.php json reply. tried one by one. But still authentication step fails. JSON output is as below:
{"control:Cleartext-Password":"hello", "request:User-Password":"hello","reply:Reply-Message":"Hello bob"}
I wonder that if the JSON response is wrong and how should it be for Authentication reply?
Thanks.
The authorize method rlm_rest module acts like other datastore modules like rlm_sql, rlm_redis and rlm_couchbase.
It is mainly for retrieving AVPs from a remote source, it can be used as an authentication module, but not in the way you were calling it above (example at the bottom of this answer).
With the way you're calling rlm_rest, In order for the user to be accepted, you'll need to list another module that can look at the attributes in the request, look at what you got back from your rest API, and figure out what type of authentication to perform. If you're doing plaintext authentication (i.e. no EAP) then you can use the pap module.
Your server config would then look something like
authorize {
rest
pap
}
authenticate {
pap
}
rest.authorize retrieves control:Cleartext-Password which gives the server the "good" password to compare against the password the user sent.
pap.authorize checks to see if request:User-Password exists, and if it does, sets control:Auth-Type pap.
pap.authenticate compares control:Cleartext-Password with request:User-Password and if they match returns ok or reject depending on whether they do or not.
The other way of authenticating a plaintext userr in this case is by using HTTP BasicAuth and rlm_rest's authenticate method. The policy for that would look something like this:
authorize {
if (&User-Password) {
update control {
Auth-Type := 'rest'
}
}
}
authenticate {
rest
}
My server program is designed to listen on all the interfaces and it is listening working also.
One strange behavior is happening. It means port conflict with sshd process. Because I need to make my application and sshd to listen on same port range.(ex: 6000 - 6100)
MyProg code:
MyPort = 6011;
#if TARGET_HAS_IPV6_SUPPORT
/* IPv6 socket */
{
struct addrinfo *ai = NULL;
r = ipw_getaddrinfo("::", NULL, AF_INET6, SOCK_STREAM, IPPROTO_TCP, AI_PASSIVE, &ai);
if (r == 0)
{
Create_listen_socket(&ai, IpcMyPort);
}
}
#endif
{
struct addrinfo ailocal = { 0 };
struct sockaddr_in sin = { 0 };
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_ANY);
ailocal.ai_family = AF_INET;
ailocal.ai_socktype = SOCK_STREAM;
ailocal.ai_protocol = IPPROTO_TCP;
ailocal.ai_flags = AI_PASSIVE;
ailocal.ai_addrlen = sizeof(struct sockaddr_in);
ailocal.ai_addr = (struct sockaddr *)&sin;
Create_listen_socket(&ailocal, MyPort);
}
Create_listen_socket(struct addrinfo *ai,
unsigned int MyPort)
{
SOCKET fd = INVALID_SOCKET;
while (ai != NULL)
{
fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (fd == INVALID_SOCKET)
{
Exit()
break;
}
switch (switch (sa->sa_family)
{
case AF_INET:
{
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
sin->sin_port = htons((unsigned short)port);
}
break;
#if TARGET_HAS_IPV6_SUPPORT
case AF_INET6:
{
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
sin6->sin6_port = htons((unsigned short)port);
}
break;
#endif
}
if (ipw_bind(fd, ai->ai_addr, ai->ai_addrlen) < 0)
{
exit();
Break;
}
else
{
r = ipw_listen(fd, IPC_MAX_LISTEN_COUNT);
}
ai = ai->ai_next;
}
}
Following is the output of "sudo lsof -i -P | grep :60"
:: :: ::
sshd 23038 fin22495 11u IPv4 0x60026f7c740 0t0 TCP
localhost:6011 (LISTEN)
myProg 23108 root 4u IPv6 0x60026e46000 0t0 TCP *:6011
(LISTEN)
myProg 23108 root 5u IPv4 0x6002658e3c0 0t0 TCP *:6011
(LISTEN)
If you see, the sshd daemon is listening on same port 6011 but on local host interface. but my program is listening on *.6011.
How to make sure myProg listening on "localhost:6011" along with *:6011 and if already some process is listening on "localhost:6011" how to detect it. It happens in Solaris.
Please let me know your views.
Thanks,
Naga
I'm not sure what you have done here because sshd should normally be listening on port 22, not 6011. The first process opening the port will get exclusive access. There are good, security-related reasons for this being so. See the tcp(7P) manpage for details - look for SO_REUSEADDR and SO_EXECLBIND.
If you see, the sshd daemon is listening on same port 6011 but on local host interface. but my program is listening on *.6011.
How to make sure myProg listening on "localhost:6011" along with *:6011 and if already some process is listening on "localhost:6011" how to detect it. It happens in Solaris.
Your application's port numbers conflict with ports used by ssh X-forwarding. Change your port numbers and be done with that.