gpt4 book ai didi

SSDP协议(protocol)-实现

转载 作者:行者123 更新时间:2023-12-02 13:11:01 55 4
gpt4 key购买 nike

我正在尝试实现 SSDP 协议(protocol),但我不确定它到底是如何工作的。 SSDP通过udp发送数据,这是明确的。如果 Controller 连接到网络,它可以通过 MSEARCH 消息搜索设备,该消息可以发送到多播地址 239.255.255.250:1900。每个设备都必须监听该地址并做出响应。但我不知道他们如何回应。我在wireshark中看到它们以单播响应,但我不知道如何确定接收响应的端口。

编辑----------------

我正在尝试使用尖峰模糊测试框架编写 ssdp 模糊器。正如我所说,我能够发送正确的数据,但无法接收响应。我将尝试粘贴一些带有简短解释的尖峰代码。有 Spike 结构,它表示要发送的数据(它存储实际数据、大小、协议(protocol)信息...)。我删除了一些变量以使其更加清晰。

struct spike {

/*total size of all data*/
unsigned long datasize;
unsigned char *databuf;
unsigned char *endbuf;
int fd; /*for holding socket or file information*/
int proto; /*1 for tcp, 2 for udp*/
struct sockaddr_in *destsockaddr;
};

现在我通过 udp 发送数据,并希望通过以下函数接收一些响应

spike_connect_udp(target,port);
spike_send();
s_read_packet();

函数实现:

int 
spike_connect_udp(char * host, int port)
{
int fd;
/*ahh, having udpstuff.c makes this stuff easy*/
fd=udpconnect(host,port);
if (fd==-1)
{
fprintf(stderr,"Couldn't udp connect to target\n");
return (0);
}
current_spike->fd=fd;
current_spike->proto=2; /*UDP*/
return 1;
}

int
udpconnect(const char * host, const unsigned short port )
{
int sfd = -1;
struct sockaddr_in addr;
/* Translate hostname from DNS or IP-address form */

memset(&addr, 0, sizeof(addr));
if (!getHostAddress(host, &addr))
{
hdebug("can't resolve host or address.\n");
return -1;
}
addr.sin_family = AF_INET;
addr.sin_port = ntohs(port);

if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
hdebug("Could not create socket!\n");
return -1;
}

/* Now connect! */

if (connect(sfd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
close(sfd);
return -1;
}

return sfd;

}

int
spike_send()
{
int retval;

switch (current_spike->proto)
{
case 1: /*TCP*/
//deleted, doesnt matter, i am sending via udp
case 2: /*UDP*/
//udp_write_data is function from framework
retval=udp_write_data(current_spike->fd, current_spike->destsockaddr, s_get_size(), s_get_databuf());
break;

}

fflush(0);

return retval;
}

这工作正常并通过 udp 发送数据。现在我想通过打开套接字 current_spike->fd 接收一些响应。函数 s_read_packet无效

s_read_packet()
{
unsigned char buffer[5000];
int i;
int size;
s_fd_wait();
printf("Reading packet\n");
memset(buffer,0x00,sizeof(buffer));
/what alarm and fcntl does?
alarm(1);
fcntl(current_spike->fd, F_SETFL, O_NONBLOCK);
//this read return error -1 and sets errno to 11 service temporarily unavailable
size=read(current_spike->fd,buffer,1500);
fcntl(current_spike->fd, F_SETFL, 0);
alarm(0);

for (i=0; i<size; i++)
{
if (isprint(buffer[i]))
printf("%c",buffer[i]);
else
printf("[%2.2x]",buffer[i]);
}

printf("\nDone with read\n");
}

int
s_fd_wait()
{
/*this function does a select to wait for
input on the fd, and if there
is, returns 1, else 0 */
int fd;
fd_set rfds;
struct timeval tv;
int retval;

fd=current_spike->fd;

/* Watch server_fd (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
/* Wait up to zero seconds . will this wait forever? not on linux.*/

/* from man page: timeout is an upper bound on the amount of time
elapsed before select returns. It may be zero, causing select
to return immediately. If timeout is NULL (no timeout), select
can block indefinitely. */

/*wait 2 seconds only*/
tv.tv_sec = TIMEINSECONDS;
tv.tv_usec = TIMEINUSECONDS;
//printf("Before select %d:%d\n",TIMEINSECONDS,TIMEINUSECONDS);
retval = select(fd+1, &rfds, NULL, NULL, &tv);
/* Don't rely on the value of tv now! */
//printf("After select retval=%d.\n",retval);
switch (retval)
{
case 0:
/*Timeout - no packet or keypress*/
return(0);
break;
case -1:
/* ignore interrupted system calls */
if (errno != EINTR)
{
/*some kind of weird select error. Die. */
exit(-1);
}
/*otherwise we got interrupted, so just return false*/
return (0);
break;
default:
{
if (FD_ISSET(fd,&rfds))
return (1);
else
return (0);
}
}
}

但是函数 s_read_packet 没有产生数据...

最佳答案

为了实现 SSDP,您的应用程序需要能够将 NOTIFYM-SEARCH header 发送到指定的多播地址,并且还应该能够接收这些消息。为此,您需要创建一个专门的 UDP 套接字。

以下是如何初始化此类套接字的示例:

// Structs needed
struct in_addr localInterface;
struct sockaddr_in groupSock;
struct sockaddr_in localSock;
struct ip_mreq group;

// Create the Socket
int udpSocket = socket(AF_INET, SOCK_DGRAM, 0);

// Enable SO_REUSEADDR to allow multiple instances of this application to receive copies of the multicast datagrams.
int reuse = 1;

setsockopt(udpSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse));

// Initialize the group sockaddr structure with a group address of 239.255.255.250 and port 1900.
memset((char *) &groupSock, 0, sizeof(groupSock));

groupSock.sin_family = AF_INET;
groupSock.sin_addr.s_addr = inet_addr("239.255.255.250");
groupSock.sin_port = htons(1900);

// Disable loopback so you do not receive your own datagrams.
char loopch = 0;

setsockopt(udpSocket, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loopch, sizeof(loopch));

// Set local interface for outbound multicast datagrams. The IP address specified must be associated with a local, multicast capable interface.
localInterface.s_addr = inet_addr("192.168.0.1");

setsockopt(udpSocket, IPPROTO_IP, IP_MULTICAST_IF, (char *)&localInterface, sizeof(localInterface));

// Bind to the proper port number with the IP address specified as INADDR_ANY.
memset((char *) &localSock, 0, sizeof(localSock));
localSock.sin_family = AF_INET;
localSock.sin_port = htons(1900);
localSock.sin_addr.s_addr = INADDR_ANY;

bind(udpSocket, (struct sockaddr*)&localSock, sizeof(localSock));

// Join the multicast group on the local interface. Note that this IP_ADD_MEMBERSHIP option must be called for each local interface over which the multicast datagrams are to be received.
group.imr_multiaddr.s_addr = inet_addr("239.255.255.250");
group.imr_interface.s_addr = inet_addr("192.168.0.1");

setsockopt(udpSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group));

现在您可以使用此套接字将数据发送到多播组:

sendto(udpSocket, message, message_length, 0, (struct sockaddr*)&groupSock, sizeof(groupSock));

要接收消息,请执行以下操作:

struct sockaddr_in si_other;
socklen_t slen = sizeof(si_other);
char buffer[1024];

recvfrom(udpSocket, buffer, 1024, 0, (struct sockaddr *) &si_other, &slen);

要响应特定请求(如上所述收到),请执行以下操作:

sendto(udpSocket, message, message_length, 0, (struct sockaddr*)&si_other, sizeof(si_other));

您现在要做的就是创建发送所需的消息并处理接收到的数据。假设您向多播组发送 M-SEARCH 请求(如上所述),那么您将从每个设备获得如下响应:

HTTP/1.1 200 OK
SERVER: Linux/2.6.15.2 UPnP/1.0 Mediaserver/1.0
CACHE-CONTROL: max-age=1200
LOCATION: http://192.168.0.223:5001/description.xml
ST: urn:schemas-upnp-org:device:MediaServer:4
USN: uuid:550e8400-e29b-11d4-a716-446655440000::urn:schemas-upnp-org:device:MediaServer:4
Content-Length: 0
EXT:

关于SSDP协议(protocol)-实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13382469/

55 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com