统一以太网接口,2860和5500均升级,未测试
统一DHCP,简单测试,成功发出Request,收到Offer,但是程序未处理
This commit is contained in:
parent
97c560deae
commit
e772547197
|
@ -1020,7 +1020,8 @@ void HardSocket::OnClose()
|
|||
Remote.Show(true);
|
||||
}
|
||||
|
||||
int HardSocket::ReadByteArray(ByteArray& bs)
|
||||
// 接收数据
|
||||
uint HardSocket::Receive(ByteArray& bs)
|
||||
{
|
||||
// 读取收到数据容量
|
||||
ushort size = __REV16(SocRegRead2(RX_RSR));
|
||||
|
@ -1049,7 +1050,8 @@ int HardSocket::ReadByteArray(ByteArray& bs)
|
|||
return size;
|
||||
}
|
||||
|
||||
bool HardSocket::WriteByteArray(const ByteArray& bs)
|
||||
// 发送数据
|
||||
bool HardSocket::Send(const ByteArray& bs)
|
||||
{
|
||||
// 读取状态
|
||||
byte st = ReadStatus();
|
||||
|
@ -1075,7 +1077,7 @@ bool HardSocket::WriteByteArray(const ByteArray& bs)
|
|||
bool HardSocket::OnWrite(const byte* buf, uint len)
|
||||
{
|
||||
ByteArray bs(buf,len);
|
||||
return WriteByteArray(bs);
|
||||
return Send(bs);
|
||||
}
|
||||
|
||||
uint HardSocket::OnRead(byte* buf, uint len)
|
||||
|
@ -1083,7 +1085,7 @@ uint HardSocket::OnRead(byte* buf, uint len)
|
|||
ByteArray bs(buf, len);
|
||||
|
||||
// 不容 ByteArray 偷梁换柱把buf换掉
|
||||
return ReadByteArray(bs);
|
||||
return Receive(bs);
|
||||
}
|
||||
|
||||
void HardSocket::ClearRX()
|
||||
|
@ -1120,7 +1122,7 @@ void HardSocket::ReceiveTask(void* param)
|
|||
assert_ptr(param);
|
||||
|
||||
HardSocket* socket = (HardSocket*)param;
|
||||
socket->Receive();
|
||||
socket->RaiseReceive();
|
||||
}
|
||||
|
||||
void HardSocket::Register(TransportHandler handler, void* param)
|
||||
|
@ -1239,7 +1241,7 @@ void TcpClient::OnProcess(byte reg)
|
|||
else
|
||||
{
|
||||
ByteArray bs;
|
||||
int size = ReadByteArray(bs);
|
||||
int size = Receive(bs);
|
||||
debug_printf("收到数据:");
|
||||
bs.Show();
|
||||
debug_printf("\r\n");
|
||||
|
@ -1274,10 +1276,10 @@ void TcpClient::OnProcess(byte reg)
|
|||
}
|
||||
|
||||
// 异步中断
|
||||
void TcpClient::Receive()
|
||||
void TcpClient::RaiseReceive()
|
||||
{
|
||||
ByteArray bs;
|
||||
int size = ReadByteArray(bs);
|
||||
int size = Receive(bs);
|
||||
if(size > 1500)return;
|
||||
|
||||
// 回调中断
|
||||
|
@ -1308,7 +1310,7 @@ void UdpClient::OnProcess(byte reg)
|
|||
else
|
||||
{
|
||||
ByteArray bs;
|
||||
int size = ReadByteArray(bs);
|
||||
int size = Receive(bs);
|
||||
debug_printf("收到数据:");
|
||||
bs.Show();
|
||||
debug_printf("\r\n");
|
||||
|
@ -1320,13 +1322,13 @@ void UdpClient::OnProcess(byte reg)
|
|||
|
||||
// UDP 异步只有一种情况 收到数据 可能有多个数据包
|
||||
// UDP接收到的数据结构: RemoteIP(4 byte) + RemotePort(2 byte) + Length(2 byte) + Data(Length byte)
|
||||
void UdpClient::Receive()
|
||||
void UdpClient::RaiseReceive()
|
||||
{
|
||||
// UDP 异步只有一种情况 收到数据 可能有多个数据包
|
||||
// UDP接收到的数据结构: RemoteIP(4 byte) + RemotePort(2 byte) + Length(2 byte) + Data(Length byte)
|
||||
byte buf[1024];
|
||||
ByteArray bs(buf, ArrayLength(buf));
|
||||
ushort size = ReadByteArray(bs);
|
||||
ushort size = Receive(bs);
|
||||
Stream ms(bs.GetBuffer(), size);
|
||||
|
||||
// 拆包
|
||||
|
@ -1358,7 +1360,7 @@ void UdpClient::Receive()
|
|||
// {
|
||||
// // 读取包头
|
||||
// ByteArray bsHead(packetHead, ArrayLength(packetHead));
|
||||
// ushort size = ReadByteArray(bsHead, true);
|
||||
// ushort size = Receive(bsHead, true);
|
||||
// if(size == ArrayLength(packetHead))
|
||||
// {
|
||||
// // 解析头
|
||||
|
@ -1405,7 +1407,7 @@ void UdpClient::Receive()
|
|||
// if(RemainLength < DataLength) return;
|
||||
// // 读取数据
|
||||
// ByteArray bsData(dataBuf, DataLength);
|
||||
// ushort datasize = ReadByteArray(bsData, true);
|
||||
// ushort datasize = Receive(bsData, true);
|
||||
//
|
||||
// // debug_printf("Data: ");
|
||||
// // bsData.Show();
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
class HardSocket;
|
||||
|
||||
// W5500以太网驱动
|
||||
class W5500
|
||||
class W5500 : public ISocketHost
|
||||
{
|
||||
private:
|
||||
friend class HardSocket;
|
||||
|
@ -48,14 +48,6 @@ public:
|
|||
|
||||
bool Opened; // 是否已经打开
|
||||
|
||||
IPAddress IP; // 本地IP地址
|
||||
IPAddress Mask; // 子网掩码
|
||||
MacAddress Mac; // 本地Mac地址
|
||||
|
||||
IPAddress DHCPServer;
|
||||
IPAddress DNSServer;
|
||||
IPAddress Gateway;
|
||||
|
||||
// 构造
|
||||
W5500();
|
||||
W5500(Spi* spi, Pin irq = P0 ,Pin rst = P0); // 必须具备复位引脚 否则寄存器不能读
|
||||
|
@ -114,9 +106,6 @@ public:
|
|||
W5500* Host; // W5500公共部分控制器
|
||||
uint _tidRecv; // 收数据线程
|
||||
|
||||
//IPEndPoint Remote; // 远程地址。默认发送数据的目标地址
|
||||
//IPEndPoint Local; // 本地地址
|
||||
|
||||
HardSocket(W5500* host, byte protocol);
|
||||
virtual ~HardSocket();
|
||||
|
||||
|
@ -127,12 +116,14 @@ public:
|
|||
virtual bool OnOpen();
|
||||
virtual void OnClose();
|
||||
|
||||
bool WriteByteArray(const ByteArray& bs);
|
||||
int ReadByteArray(ByteArray& bs);
|
||||
|
||||
virtual bool OnWrite(const byte* buf, uint len);
|
||||
virtual uint OnRead(byte* buf, uint len);
|
||||
|
||||
// 发送数据
|
||||
virtual bool Send(const ByteArray& bs);
|
||||
// 接收数据
|
||||
virtual uint Receive(ByteArray& bs);
|
||||
|
||||
static void ReceiveTask(void* param);
|
||||
virtual void Register(TransportHandler handler, void* param);
|
||||
|
||||
|
@ -142,7 +133,7 @@ public:
|
|||
void Process();
|
||||
virtual void OnProcess(byte reg) = 0;
|
||||
// 用户注册的中断事件处理 异步调用
|
||||
virtual void Receive() = 0;
|
||||
virtual void RaiseReceive() = 0;
|
||||
// 清空所有接收缓冲区
|
||||
void ClearRX();
|
||||
};
|
||||
|
@ -163,7 +154,7 @@ public:
|
|||
// 中断分发 维护状态
|
||||
virtual void OnProcess(byte reg);
|
||||
// 用户注册的中断事件处理 异步调用
|
||||
virtual void Receive();
|
||||
virtual void RaiseReceive();
|
||||
|
||||
private:
|
||||
bool Linked;
|
||||
|
@ -180,7 +171,7 @@ public:
|
|||
// 中断分发 维护状态
|
||||
virtual void OnProcess(byte reg);
|
||||
// 用户注册的中断事件处理 异步调用
|
||||
virtual void Receive();
|
||||
virtual void RaiseReceive();
|
||||
|
||||
private:
|
||||
// 数据包头和数据分开读取
|
||||
|
|
|
@ -1,20 +1,25 @@
|
|||
#include "Time.h"
|
||||
#include "Stream.h"
|
||||
#include "ITransport.h"
|
||||
|
||||
#include "Dhcp.h"
|
||||
|
||||
#define NET_DEBUG DEBUG
|
||||
|
||||
Dhcp::Dhcp(TinyIP* tip) : UdpSocket(tip)
|
||||
Dhcp::Dhcp(ISocket* socket)
|
||||
{
|
||||
Type = IP_UDP;
|
||||
Local.Port = 68;
|
||||
Remote.Port = 67;
|
||||
Remote.Address = IPAddress::Broadcast();
|
||||
Socket = socket;
|
||||
Host = socket->Host;
|
||||
|
||||
Running = false;
|
||||
Result = false;
|
||||
ExpiredTime = 10;
|
||||
socket->Local.Port = 68;
|
||||
socket->Remote.Port = 67;
|
||||
socket->Remote.Address = IPAddress::Broadcast();
|
||||
|
||||
OnStop = NULL;
|
||||
Running = false;
|
||||
Result = false;
|
||||
ExpiredTime = 10;
|
||||
|
||||
OnStop = NULL;
|
||||
}
|
||||
|
||||
void Dhcp::SendDhcp(DHCP_HEADER& dhcp, uint len)
|
||||
|
@ -24,9 +29,9 @@ void Dhcp::SendDhcp(DHCP_HEADER& dhcp, uint len)
|
|||
{
|
||||
// 此时指向的是负载数据后的第一个字节,所以第一个opt不许Next
|
||||
DHCP_OPT* opt = (DHCP_OPT*)(p + len);
|
||||
opt = opt->SetClientId(Tip->Mac);
|
||||
if(!Tip->IP.IsAny())
|
||||
opt = opt->Next()->SetData(DHCP_OPT_RequestedIP, Tip->IP.Value);
|
||||
opt = opt->SetClientId(Host->Mac);
|
||||
if(!Host->IP.IsAny())
|
||||
opt = opt->Next()->SetData(DHCP_OPT_RequestedIP, Host->IP.Value);
|
||||
|
||||
// 构造产品名称,把ID第一个字节附到最后
|
||||
String name;
|
||||
|
@ -44,13 +49,12 @@ void Dhcp::SendDhcp(DHCP_HEADER& dhcp, uint len)
|
|||
len = (byte*)opt + 1 - p;
|
||||
}
|
||||
|
||||
//memcpy(dhcp->ClientMac, (byte*)&Tip->Mac.Value, 6);
|
||||
for(int i=0; i<6; i++)
|
||||
dhcp.ClientMac[i] = Tip->Mac[i];
|
||||
dhcp.ClientMac[i] = Host->Mac[i];
|
||||
|
||||
//RemoteIP = IPAddress::Broadcast;
|
||||
|
||||
Send(*dhcp.Prev(), sizeof(DHCP_HEADER) + len, Remote.Address, Remote.Port, false);
|
||||
//Send(*dhcp.Prev(), sizeof(DHCP_HEADER) + len, Remote.Address, Remote.Port, false);
|
||||
ByteArray bs((byte*)&dhcp, sizeof(DHCP_HEADER) + len);
|
||||
Socket->Send(bs);
|
||||
}
|
||||
|
||||
// 获取选项,返回数据部分指针
|
||||
|
@ -86,7 +90,7 @@ void Dhcp::Request(DHCP_HEADER& dhcp)
|
|||
DHCP_OPT* opt = (DHCP_OPT*)p;
|
||||
opt->SetType(DHCP_TYPE_Request);
|
||||
|
||||
opt = opt->Next()->SetData(DHCP_OPT_DHCPServer, Tip->DHCPServer.Value);
|
||||
opt = opt->Next()->SetData(DHCP_OPT_DHCPServer, Host->DHCPServer.Value);
|
||||
|
||||
// 发往DHCP服务器
|
||||
SendDhcp(dhcp, (byte*)opt->Next() - p);
|
||||
|
@ -102,10 +106,10 @@ void Dhcp::PareOption(Stream& ms)
|
|||
// 有些家用路由器会发送错误的len,大于4字节,导致覆盖前后数据
|
||||
switch(opt)
|
||||
{
|
||||
case DHCP_OPT_Mask: Tip->Mask = ms.Read<int>(); len -= 4; break;
|
||||
case DHCP_OPT_DNSServer: Tip->DNSServer = ms.Read<int>(); len -= 4; break;
|
||||
case DHCP_OPT_Router: Tip->Gateway = ms.Read<int>(); len -= 4; break;
|
||||
case DHCP_OPT_DHCPServer: Tip->DHCPServer = ms.Read<int>(); len -= 4; break;
|
||||
case DHCP_OPT_Mask: Host->Mask = ms.Read<int>(); len -= 4; break;
|
||||
case DHCP_OPT_DNSServer: Host->DNSServer = ms.Read<int>(); len -= 4; break;
|
||||
case DHCP_OPT_Router: Host->Gateway = ms.Read<int>(); len -= 4; break;
|
||||
case DHCP_OPT_DHCPServer: Host->DHCPServer = ms.Read<int>(); len -= 4; break;
|
||||
//default:
|
||||
// debug_printf("Unkown DHCP Option=%d Length=%d\r\n", opt, len);
|
||||
}
|
||||
|
@ -116,13 +120,11 @@ void Dhcp::PareOption(Stream& ms)
|
|||
|
||||
void RenewDHCP(void* param)
|
||||
{
|
||||
TinyIP* tip = (TinyIP*)param;
|
||||
if(tip)
|
||||
ISocket* socket = (ISocket*)param;
|
||||
if(socket)
|
||||
{
|
||||
/*Dhcp dhcp(tip);
|
||||
dhcp.Start();*/
|
||||
// 不能使用栈分配,因为是异步操作
|
||||
Dhcp* dhcp = new Dhcp(tip);
|
||||
Dhcp* dhcp = new Dhcp(socket);
|
||||
dhcp->Start();
|
||||
}
|
||||
}
|
||||
|
@ -135,38 +137,25 @@ void Dhcp::Start()
|
|||
debug_printf("Dhcp::Start ExpiredTime=%ds DhcpID=0x%08x\r\n", ExpiredTime, dhcpid);
|
||||
|
||||
// 创建任务,每秒发送一次Discover
|
||||
//debug_printf("Dhcp发送Discover ");
|
||||
taskID = Sys.AddTask(SendDiscover, this, 0, 1000000, "DHCP");
|
||||
|
||||
// 通过DHCP获取IP期间,关闭Arp响应
|
||||
//Tip->EnableArp = false;
|
||||
if(Tip->Arp) Tip->Arp->Enable = false;
|
||||
|
||||
Running = true;
|
||||
|
||||
Open();
|
||||
ITransport* port = dynamic_cast<ITransport*>(Socket);
|
||||
if(port) port->Open();
|
||||
}
|
||||
|
||||
void Dhcp::Stop()
|
||||
{
|
||||
Close();
|
||||
ITransport* port = dynamic_cast<ITransport*>(Socket);
|
||||
if(port) port->Close();
|
||||
|
||||
Running = false;
|
||||
if(taskID)
|
||||
{
|
||||
debug_printf("Dhcp发送Discover ");
|
||||
Sys.RemoveTask(taskID);
|
||||
}
|
||||
taskID = 0;
|
||||
|
||||
// 通过DHCP获取IP期间,关闭Arp响应
|
||||
//Tip->EnableArp = true;
|
||||
if(Tip->Arp) Tip->Arp->Enable = true;
|
||||
Running = false;
|
||||
Sys.RemoveTask(taskID);
|
||||
taskID = 0;
|
||||
|
||||
debug_printf("Dhcp::Stop Result=%d DhcpID=0x%08x\r\n", Result, dhcpid);
|
||||
|
||||
if(Result) Tip->ShowInfo();
|
||||
|
||||
if(OnStop) OnStop(this, NULL);
|
||||
|
||||
// 销毁自己
|
||||
|
@ -213,10 +202,10 @@ void Dhcp::OnProcess(IP_HEADER& ip, UDP_HEADER& udp, Stream& ms)
|
|||
if(__REV(dhcp->TransID) != dhcpid) return;
|
||||
|
||||
IPAddress remote = ip.SrcIP;
|
||||
|
||||
|
||||
if(opt->Data == DHCP_TYPE_Offer)
|
||||
{
|
||||
Tip->IP = dhcp->YourIP;
|
||||
Host->IP = dhcp->YourIP;
|
||||
Stream optData(dhcp->Next(), len);
|
||||
PareOption(optData);
|
||||
|
||||
|
@ -224,7 +213,7 @@ void Dhcp::OnProcess(IP_HEADER& ip, UDP_HEADER& udp, Stream& ms)
|
|||
// 这里其实还应该发送ARP包确认IP是否被占用,如果被占用,还需要拒绝服务器提供的IP,比较复杂,可能性很低,暂时不考虑
|
||||
#if NET_DEBUG
|
||||
debug_printf("DHCP::Offer IP:");
|
||||
Tip->IP.Show();
|
||||
Host->IP.Show();
|
||||
debug_printf(" From ");
|
||||
remote.Show();
|
||||
debug_printf("\r\n");
|
||||
|
@ -242,7 +231,7 @@ void Dhcp::OnProcess(IP_HEADER& ip, UDP_HEADER& udp, Stream& ms)
|
|||
}
|
||||
else if(opt->Data == DHCP_TYPE_Ack)
|
||||
{
|
||||
Tip->IP = dhcp->YourIP;
|
||||
Host->IP = dhcp->YourIP;
|
||||
#if NET_DEBUG
|
||||
debug_printf("DHCP::Ack IP:");
|
||||
IPAddress(dhcp->YourIP).Show();
|
||||
|
@ -251,7 +240,7 @@ void Dhcp::OnProcess(IP_HEADER& ip, UDP_HEADER& udp, Stream& ms)
|
|||
debug_printf("\r\n");
|
||||
#endif
|
||||
|
||||
//if(dhcp->YourIP == Tip->IP)
|
||||
//if(dhcp->YourIP == Host->IP)
|
||||
{
|
||||
// 查找租约时间,提前续约
|
||||
opt = GetOption(data, len, DHCP_OPT_IPLeaseTime);
|
||||
|
@ -266,7 +255,7 @@ void Dhcp::OnProcess(IP_HEADER& ip, UDP_HEADER& udp, Stream& ms)
|
|||
if(time > 0)
|
||||
{
|
||||
//debug_printf("Dhcp过期获取 ");
|
||||
Sys.AddTask(RenewDHCP, Tip, (ulong)time / 2 * 1000000, -1, "DHCP超时");
|
||||
Sys.AddTask(RenewDHCP, Socket, (ulong)time / 2 * 1000000, -1, "DHCP超时");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,7 +271,7 @@ void Dhcp::OnProcess(IP_HEADER& ip, UDP_HEADER& udp, Stream& ms)
|
|||
// 导致Nak的原因
|
||||
opt = GetOption(data, len, DHCP_OPT_Message);
|
||||
debug_printf("DHCP::Nak IP:");
|
||||
Tip->IP.Show();
|
||||
Host->IP.Show();
|
||||
debug_printf(" From ");
|
||||
remote.Show();
|
||||
if(opt)
|
|
@ -1,10 +1,11 @@
|
|||
#ifndef _TinyIP_DHCP_H_
|
||||
#define _TinyIP_DHCP_H_
|
||||
|
||||
#include "Udp.h"
|
||||
#include "Net.h"
|
||||
#include "Ethernet.h"
|
||||
|
||||
// DHCP协议
|
||||
class Dhcp : public UdpSocket
|
||||
class Dhcp
|
||||
{
|
||||
private:
|
||||
uint dhcpid;
|
||||
|
@ -20,11 +21,14 @@ private:
|
|||
|
||||
static void SendDiscover(void* param);
|
||||
public:
|
||||
ISocket* Socket;
|
||||
ISocketHost* Host; // 主机
|
||||
|
||||
bool Running; // 正在运行
|
||||
bool Result; // 是否获取IP成功
|
||||
uint ExpiredTime; // 过期时间
|
||||
|
||||
Dhcp(TinyIP* tip);
|
||||
Dhcp(ISocket* socket);
|
||||
|
||||
void Start(); // 开始
|
||||
void Stop(); // 停止
|
20
Net/Net.h
20
Net/Net.h
|
@ -98,13 +98,33 @@ public:
|
|||
static const MacAddress& Full();
|
||||
};
|
||||
|
||||
// Socket主机
|
||||
class ISocketHost
|
||||
{
|
||||
public:
|
||||
IPAddress IP; // 本地IP地址
|
||||
IPAddress Mask; // 子网掩码
|
||||
MacAddress Mac; // 本地Mac地址
|
||||
|
||||
IPAddress DHCPServer;
|
||||
IPAddress DNSServer;
|
||||
IPAddress Gateway;
|
||||
};
|
||||
|
||||
// Socket接口
|
||||
class ISocket
|
||||
{
|
||||
public:
|
||||
ISocketHost* Host; // 主机
|
||||
|
||||
//ushort Port; // 本地端口。用于过滤数据,默认0表示接收所有端口的数据
|
||||
IPEndPoint Local; // 本地地址。包含本地局域网IP地址,实际监听的端口,从1024开始累加
|
||||
IPEndPoint Remote; // 远程地址
|
||||
|
||||
// 发送数据
|
||||
virtual bool Send(const ByteArray& bs) = 0;
|
||||
// 接收数据
|
||||
virtual uint Receive(ByteArray& bs) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,7 +19,7 @@ public:
|
|||
|
||||
ArpSession* _ArpSession;
|
||||
|
||||
ArpSocket::ArpSocket(TinyIP* tip) : Socket(tip, IP_NONE)
|
||||
ArpSocket::ArpSocket(TinyIP* tip) : TinySocket(tip, IP_NONE)
|
||||
{
|
||||
//Type = IP_NONE;
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include "TinyIP.h"
|
||||
|
||||
// ARP协议
|
||||
class ArpSocket : public Socket
|
||||
class ArpSocket : public TinySocket
|
||||
{
|
||||
private:
|
||||
// ARP表
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
// 用于等待Ping响应的会话
|
||||
PingSession* _IcmpSession = NULL;
|
||||
|
||||
IcmpSocket::IcmpSocket(TinyIP* tip) : Socket(tip, IP_ICMP)
|
||||
IcmpSocket::IcmpSocket(TinyIP* tip) : TinySocket(tip, IP_ICMP)
|
||||
{
|
||||
//Type = IP_ICMP;
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "TinyIP.h"
|
||||
|
||||
// ICMP协议
|
||||
class IcmpSocket : public Socket
|
||||
class IcmpSocket : public TinySocket
|
||||
{
|
||||
public:
|
||||
IcmpSocket(TinyIP* tip);
|
||||
|
|
|
@ -8,7 +8,7 @@ bool* WaitAck;
|
|||
|
||||
bool Callback(TinyIP* tip, void* param, Stream& ms);
|
||||
|
||||
TcpSocket::TcpSocket(TinyIP* tip) : Socket(tip, IP_TCP)
|
||||
TcpSocket::TcpSocket(TinyIP* tip) : TinySocket(tip, IP_TCP)
|
||||
{
|
||||
//Port = 0;
|
||||
|
||||
|
@ -150,9 +150,9 @@ void TcpSocket::OnAccept(TCP_HEADER& tcp, uint len)
|
|||
SetMss(tcp);
|
||||
|
||||
// 需要用到MSS,所以采用4个字节的可选段
|
||||
//Send(tcp, 4, TCP_FLAGS_SYN | TCP_FLAGS_ACK);
|
||||
//SendPacket(tcp, 4, TCP_FLAGS_SYN | TCP_FLAGS_ACK);
|
||||
// 注意tcp->Size()包括头部的扩展数据,这里不用单独填4
|
||||
Send(tcp, 0, TCP_FLAGS_SYN | TCP_FLAGS_ACK);
|
||||
SendPacket(tcp, 0, TCP_FLAGS_SYN | TCP_FLAGS_ACK);
|
||||
}
|
||||
|
||||
// 客户端收到握手三,也是首次收到来自服务端的数据,或者0数据的ACK
|
||||
|
@ -176,7 +176,7 @@ void TcpSocket::OnAccept3(TCP_HEADER& tcp, uint len)
|
|||
// 不需要Mss
|
||||
tcp.Length = sizeof(TCP_HEADER) / 4;
|
||||
|
||||
Send(tcp, 0, TCP_FLAGS_ACK);
|
||||
SendPacket(tcp, 0, TCP_FLAGS_ACK);
|
||||
}
|
||||
|
||||
void TcpSocket::OnDataReceive(TCP_HEADER& tcp, uint len)
|
||||
|
@ -187,7 +187,7 @@ void TcpSocket::OnDataReceive(TCP_HEADER& tcp, uint len)
|
|||
if (tcp.Flags & (TCP_FLAGS_FIN | TCP_FLAGS_RST)) //FIN结束连接请求标志位。为1表示是结束连接的请求数据包
|
||||
{
|
||||
SetSeqAck(tcp, 1, true);
|
||||
Send(tcp, 0, TCP_FLAGS_ACK);
|
||||
SendPacket(tcp, 0, TCP_FLAGS_ACK);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -211,7 +211,7 @@ void TcpSocket::OnDataReceive(TCP_HEADER& tcp, uint len)
|
|||
SetSeqAck(tcp, len, true);
|
||||
|
||||
// 响应Ack和发送数据一步到位
|
||||
Send(tcp, len2, TCP_FLAGS_ACK | TCP_FLAGS_PUSH);
|
||||
SendPacket(tcp, len2, TCP_FLAGS_ACK | TCP_FLAGS_PUSH);
|
||||
}
|
||||
|
||||
if(OnReceived)
|
||||
|
@ -223,7 +223,7 @@ void TcpSocket::OnDataReceive(TCP_HEADER& tcp, uint len)
|
|||
{
|
||||
// 发送ACK,通知已收到
|
||||
SetSeqAck(tcp, len, true);
|
||||
Send(tcp, 0, TCP_FLAGS_ACK);
|
||||
SendPacket(tcp, 0, TCP_FLAGS_ACK);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -239,10 +239,10 @@ void TcpSocket::OnDataReceive(TCP_HEADER& tcp, uint len)
|
|||
}
|
||||
// 发送ACK,通知已收到
|
||||
SetSeqAck(tcp, len, true);
|
||||
Send(tcp, 0, TCP_FLAGS_ACK);
|
||||
SendPacket(tcp, 0, TCP_FLAGS_ACK);
|
||||
|
||||
// 响应Ack和发送数据一步到位
|
||||
//Send(tcp, len, TCP_FLAGS_ACK | TCP_FLAGS_PUSH);
|
||||
//SendPacket(tcp, len, TCP_FLAGS_ACK | TCP_FLAGS_PUSH);
|
||||
}
|
||||
|
||||
void TcpSocket::OnDisconnect(TCP_HEADER& tcp, uint len)
|
||||
|
@ -256,7 +256,7 @@ void TcpSocket::OnDisconnect(TCP_HEADER& tcp, uint len)
|
|||
{
|
||||
SetSeqAck(tcp, 1, true);
|
||||
//Close(tcp, 0);
|
||||
Send(tcp, 0, TCP_FLAGS_ACK | TCP_FLAGS_PUSH | TCP_FLAGS_FIN);
|
||||
SendPacket(tcp, 0, TCP_FLAGS_ACK | TCP_FLAGS_PUSH | TCP_FLAGS_FIN);
|
||||
}
|
||||
else if(!OnDisconnected)
|
||||
{
|
||||
|
@ -271,7 +271,7 @@ void TcpSocket::OnDisconnect(TCP_HEADER& tcp, uint len)
|
|||
Status = Closed;
|
||||
}
|
||||
|
||||
bool TcpSocket::Send(TCP_HEADER& tcp, uint len, byte flags)
|
||||
bool TcpSocket::SendPacket(TCP_HEADER& tcp, uint len, byte flags)
|
||||
{
|
||||
tcp.SrcPort = __REV16(Local.Port);
|
||||
tcp.DestPort = __REV16(Remote.Port);
|
||||
|
@ -344,7 +344,7 @@ void TcpSocket::SendAck(uint len)
|
|||
|
||||
TCP_HEADER* tcp = ms.Retrieve<TCP_HEADER>();
|
||||
tcp->Init(true);
|
||||
Send(*tcp, len, TCP_FLAGS_ACK | TCP_FLAGS_PUSH);
|
||||
SendPacket(*tcp, len, TCP_FLAGS_ACK | TCP_FLAGS_PUSH);
|
||||
}
|
||||
|
||||
bool TcpSocket::Disconnect()
|
||||
|
@ -358,10 +358,10 @@ bool TcpSocket::Disconnect()
|
|||
|
||||
TCP_HEADER* tcp = ms.Retrieve<TCP_HEADER>();
|
||||
tcp->Init(true);
|
||||
return Send(*tcp, 0, TCP_FLAGS_ACK | TCP_FLAGS_PUSH | TCP_FLAGS_FIN);
|
||||
return SendPacket(*tcp, 0, TCP_FLAGS_ACK | TCP_FLAGS_PUSH | TCP_FLAGS_FIN);
|
||||
}
|
||||
|
||||
bool TcpSocket::Send(ByteArray& bs)
|
||||
bool TcpSocket::Send(const ByteArray& bs)
|
||||
{
|
||||
if(!Enable)
|
||||
{
|
||||
|
@ -396,7 +396,7 @@ bool TcpSocket::Send(ByteArray& bs)
|
|||
tcp->Ack = __REV(Ack);
|
||||
// 发送数据的时候,需要同时带PUSH和ACK
|
||||
//debug_printf("Seq=0x%04x Ack=0x%04x \r\n", Seq, Ack);
|
||||
if(!Send(*tcp, bs.Length(), TCP_FLAGS_PUSH | TCP_FLAGS_ACK)) return false;
|
||||
if(!SendPacket(*tcp, bs.Length(), TCP_FLAGS_PUSH | TCP_FLAGS_ACK)) return false;
|
||||
|
||||
bool wait = false;
|
||||
WaitAck = &wait;
|
||||
|
@ -420,6 +420,11 @@ bool TcpSocket::Send(ByteArray& bs)
|
|||
return wait;
|
||||
}
|
||||
|
||||
uint TcpSocket::Receive(ByteArray& bs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 连接远程服务器,记录远程服务器IP和端口,后续发送数据和关闭连接需要
|
||||
bool TcpSocket::Connect(IPAddress& ip, ushort port)
|
||||
{
|
||||
|
@ -451,7 +456,7 @@ bool TcpSocket::Connect(IPAddress& ip, ushort port)
|
|||
SetMss(*tcp);
|
||||
|
||||
Status = SynSent;
|
||||
if(!Send(*tcp, 0, TCP_FLAGS_SYN))
|
||||
if(!SendPacket(*tcp, 0, TCP_FLAGS_SYN))
|
||||
{
|
||||
Status = Closed;
|
||||
return false;
|
||||
|
|
15
TinyIP/Tcp.h
15
TinyIP/Tcp.h
|
@ -4,12 +4,12 @@
|
|||
#include "TinyIP.h"
|
||||
|
||||
// Tcp会话
|
||||
class TcpSocket : public Socket, public ITransport, public ISocket
|
||||
class TcpSocket : public TinySocket, public ITransport, public ISocket
|
||||
{
|
||||
private:
|
||||
uint Seq; // 序列号,本地发出数据包
|
||||
uint Ack; // 确认号,对方发送数据包的序列号+1
|
||||
|
||||
|
||||
public:
|
||||
// Tcp状态
|
||||
typedef enum
|
||||
|
@ -34,10 +34,15 @@ public:
|
|||
// 处理数据包
|
||||
virtual bool Process(IP_HEADER& ip, Stream& ms);
|
||||
|
||||
bool Connect(IPAddress& ip, ushort port); // 连接远程服务器,记录远程服务器IP和端口,后续发送数据和关闭连接需要
|
||||
bool Send(ByteArray& bs); // 向Socket发送数据,可能是外部数据包
|
||||
// 连接远程服务器,记录远程服务器IP和端口,后续发送数据和关闭连接需要
|
||||
bool Connect(IPAddress& ip, ushort port);
|
||||
bool Disconnect(); // 关闭Socket
|
||||
|
||||
// 发送数据
|
||||
virtual bool Send(const ByteArray& bs);
|
||||
// 接收数据
|
||||
virtual uint Receive(ByteArray& bs);
|
||||
|
||||
// 收到Tcp数据时触发,传递结构体和负载数据长度。返回值指示是否向对方发送数据包
|
||||
typedef bool (*TcpHandler)(TcpSocket& socket, TCP_HEADER& tcp, byte* buf, uint len);
|
||||
TcpHandler OnAccepted;
|
||||
|
@ -51,7 +56,7 @@ protected:
|
|||
|
||||
void SetSeqAck(TCP_HEADER& tcp, uint ackNum, bool cp_seq);
|
||||
void SetMss(TCP_HEADER& tcp);
|
||||
bool Send(TCP_HEADER& tcp, uint len, byte flags);
|
||||
bool SendPacket(TCP_HEADER& tcp, uint len, byte flags);
|
||||
|
||||
virtual void OnProcess(TCP_HEADER& tcp, Stream& ms);
|
||||
virtual void OnAccept(TCP_HEADER& tcp, uint len);
|
||||
|
|
|
@ -165,7 +165,7 @@ void TinyIP::Process(Stream& ms)
|
|||
uint count = Sockets.Count();
|
||||
for(int i=count-1; i>=0; i--)
|
||||
{
|
||||
Socket* socket = Sockets[i];
|
||||
TinySocket* socket = Sockets[i];
|
||||
if(socket && socket->Enable)
|
||||
{
|
||||
// 必须类型匹配
|
||||
|
@ -407,7 +407,7 @@ bool TinyIP::IsBroadcast(const IPAddress& ip)
|
|||
}
|
||||
#endif
|
||||
|
||||
Socket::Socket(TinyIP* tip, IP_TYPE type)
|
||||
TinySocket::TinySocket(TinyIP* tip, IP_TYPE type)
|
||||
{
|
||||
assert_param2(tip, "空的Tip");
|
||||
|
||||
|
@ -419,7 +419,7 @@ Socket::Socket(TinyIP* tip, IP_TYPE type)
|
|||
if(type != IP_NONE) tip->Sockets.Add(this);
|
||||
}
|
||||
|
||||
Socket::~Socket()
|
||||
TinySocket::~TinySocket()
|
||||
{
|
||||
assert_param2(Tip, "空的Tip");
|
||||
|
||||
|
@ -428,12 +428,12 @@ Socket::~Socket()
|
|||
Tip->Sockets.Remove(this);
|
||||
}
|
||||
|
||||
Socket* SocketList::FindByType(ushort type)
|
||||
TinySocket* SocketList::FindByType(ushort type)
|
||||
{
|
||||
uint count = Count();
|
||||
for(int i=count-1; i>=0; i--)
|
||||
{
|
||||
Socket* socket = (*this)[i];
|
||||
TinySocket* socket = (*this)[i];
|
||||
if(socket)
|
||||
{
|
||||
// 必须类型匹配
|
||||
|
|
|
@ -13,25 +13,25 @@
|
|||
class TinyIP;
|
||||
|
||||
// 网络数据处理Socket基类
|
||||
class Socket
|
||||
class TinySocket
|
||||
{
|
||||
public:
|
||||
TinyIP* Tip; // TinyIP控制器
|
||||
IP_TYPE Type; // 类型
|
||||
bool Enable; // 启用
|
||||
|
||||
Socket(TinyIP* tip, IP_TYPE type);
|
||||
virtual ~Socket();
|
||||
TinySocket(TinyIP* tip, IP_TYPE type);
|
||||
virtual ~TinySocket();
|
||||
|
||||
// 处理数据包
|
||||
virtual bool Process(IP_HEADER& ip, Stream& ms) = 0;
|
||||
};
|
||||
|
||||
// Socket列表
|
||||
class SocketList : public List<Socket*>
|
||||
class SocketList : public List<TinySocket*>
|
||||
{
|
||||
public:
|
||||
Socket* FindByType(ushort type);
|
||||
TinySocket* FindByType(ushort type);
|
||||
};
|
||||
|
||||
//class TinyIP;
|
||||
|
@ -71,7 +71,7 @@ public:
|
|||
IPAddress Gateway;
|
||||
|
||||
// Arp套接字
|
||||
Socket* Arp;
|
||||
TinySocket* Arp;
|
||||
// 套接字列表。套接字根据类型来识别
|
||||
SocketList Sockets;
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
//#define NET_DEBUG DEBUG
|
||||
#define NET_DEBUG 0
|
||||
|
||||
UdpSocket::UdpSocket(TinyIP* tip) : Socket(tip, IP_UDP)
|
||||
UdpSocket::UdpSocket(TinyIP* tip) : TinySocket(tip, IP_UDP)
|
||||
{
|
||||
//Port = 0;
|
||||
|
||||
|
@ -77,16 +77,17 @@ void UdpSocket::OnProcess(IP_HEADER& ip, UDP_HEADER& udp, Stream& ms)
|
|||
//if(len2) Write(data, len2);
|
||||
if(len2)
|
||||
{
|
||||
Remote = CurRemote;
|
||||
ByteArray bs(data, len2);
|
||||
Send(bs, CurRemote.Address, CurRemote.Port);
|
||||
Send(bs);
|
||||
}
|
||||
|
||||
if(OnReceived)
|
||||
{
|
||||
|
||||
|
||||
// 返回值指示是否向对方发送数据包
|
||||
bool rs = OnReceived(*this, udp, CurRemote, ms);
|
||||
if(rs && ms.Remain() > 0) Send(udp, len, CurRemote.Address, CurRemote.Port, false);
|
||||
if(rs && ms.Remain() > 0) SendPacket(udp, len, CurRemote.Address, CurRemote.Port, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -103,7 +104,7 @@ void UdpSocket::OnProcess(IP_HEADER& ip, UDP_HEADER& udp, Stream& ms)
|
|||
}
|
||||
}
|
||||
|
||||
void UdpSocket::Send(UDP_HEADER& udp, uint len, IPAddress& ip, ushort port, bool checksum)
|
||||
void UdpSocket::SendPacket(UDP_HEADER& udp, uint len, IPAddress& ip, ushort port, bool checksum)
|
||||
{
|
||||
uint tlen = sizeof(UDP_HEADER) + len;
|
||||
udp.SrcPort = __REV16(Local.Port);
|
||||
|
@ -128,22 +129,24 @@ void UdpSocket::Send(UDP_HEADER& udp, uint len, IPAddress& ip, ushort port, bool
|
|||
}
|
||||
|
||||
// 发送UDP数据到目标地址
|
||||
void UdpSocket::Send(ByteArray& bs, IPAddress ip, ushort port)
|
||||
bool UdpSocket::Send(const ByteArray& bs)
|
||||
{
|
||||
if(ip.IsAny()) ip = Remote.Address;
|
||||
if(!port) port = Remote.Port;
|
||||
//if(ip.IsAny()) ip = Remote.Address;
|
||||
//if(!port) port = Remote.Port;
|
||||
|
||||
byte buf[sizeof(ETH_HEADER) + sizeof(IP_HEADER) + sizeof(UDP_HEADER) + 256];
|
||||
Stream ms(buf, ArrayLength(buf));
|
||||
ms.Seek(sizeof(ETH_HEADER) + sizeof(IP_HEADER));
|
||||
|
||||
|
||||
UDP_HEADER* udp = ms.Retrieve<UDP_HEADER>();
|
||||
udp->Init(true);
|
||||
|
||||
// 复制数据,确保数据不会溢出
|
||||
ms.Write(bs);
|
||||
|
||||
Send(*udp, bs.Length(), ip, port, true);
|
||||
SendPacket(*udp, bs.Length(), Remote.Address, Remote.Port, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UdpSocket::OnWrite(const byte* buf, uint len)
|
||||
|
@ -153,6 +156,11 @@ bool UdpSocket::OnWrite(const byte* buf, uint len)
|
|||
return len;
|
||||
}
|
||||
|
||||
uint UdpSocket::Receive(ByteArray& bs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint UdpSocket::OnRead(byte* buf, uint len)
|
||||
{
|
||||
// 暂时不支持
|
||||
|
|
10
TinyIP/Udp.h
10
TinyIP/Udp.h
|
@ -4,7 +4,7 @@
|
|||
#include "TinyIP.h"
|
||||
|
||||
// Udp会话
|
||||
class UdpSocket : public Socket, public ITransport, public ISocket
|
||||
class UdpSocket : public TinySocket, public ITransport, public ISocket
|
||||
{
|
||||
private:
|
||||
|
||||
|
@ -24,13 +24,15 @@ public:
|
|||
typedef bool (*UdpHandler)(UdpSocket& socket, UDP_HEADER& udp, IPEndPoint& remote, Stream& ms);
|
||||
UdpHandler OnReceived;
|
||||
|
||||
// 发送UDP数据到目标地址
|
||||
void Send(ByteArray& bs, IPAddress ip = IPAddress::Any(), ushort port = 0);
|
||||
// 发送数据
|
||||
virtual bool Send(const ByteArray& bs);
|
||||
// 接收数据
|
||||
virtual uint Receive(ByteArray& bs);
|
||||
|
||||
virtual string ToString();
|
||||
|
||||
protected:
|
||||
void Send(UDP_HEADER& udp, uint len, IPAddress& ip, ushort port, bool checksum = true);
|
||||
void SendPacket(UDP_HEADER& udp, uint len, IPAddress& ip, ushort port, bool checksum = true);
|
||||
virtual void OnProcess(IP_HEADER& ip, UDP_HEADER& udp, Stream& ms);
|
||||
|
||||
virtual bool OnOpen();
|
||||
|
|
475
TinyIP2/Dhcp.cpp
475
TinyIP2/Dhcp.cpp
|
@ -1,475 +0,0 @@
|
|||
#include "Time.h"
|
||||
#include "Dhcp.h"
|
||||
|
||||
#define NET_DEBUG DEBUG
|
||||
|
||||
|
||||
// 字节序
|
||||
#ifndef LITTLE_ENDIAN
|
||||
#define LITTLE_ENDIAN 1
|
||||
#endif
|
||||
|
||||
#pragma pack(push) // 保存对齐状态
|
||||
// 强制结构体紧凑分配空间
|
||||
#pragma pack(1)
|
||||
|
||||
|
||||
// DHCP头部,总长度240=0xF0字节,偏移42=0x2A,后面可选数据偏移282=0x11A
|
||||
typedef struct _DHCP_HEADER
|
||||
{
|
||||
byte MsgType; // 若是client送给server的封包,设为1,反向为2
|
||||
byte HardType; // 以太网1
|
||||
byte HardLength; // 以太网6
|
||||
byte Hops; // 若数据包需经过router传送,每站加1,若在同一网内,为0
|
||||
uint TransID; // 事务ID,是个随机数,用于客户和服务器之间匹配请求和相应消息
|
||||
ushort Seconds; // 由用户指定的时间,指开始地址获取和更新进行后的时间
|
||||
ushort Flags; // 从0-15bits,最左一bit为1时表示server将以广播方式传送封包给 client,其余尚未使用
|
||||
IPAddr ClientIP; // 客户机IP
|
||||
IPAddr YourIP; // 你的IP
|
||||
IPAddr ServerIP; // 服务器IP
|
||||
IPAddr RelayIP; // 中继代理IP
|
||||
byte ClientMac[16]; // 客户端硬件地址
|
||||
byte ServerName[64]; // 服务器名
|
||||
byte BootFile[128]; // 启动文件名
|
||||
uint Magic; // 幻数0x63825363,小端0x63538263
|
||||
|
||||
void Init(uint dhcpid, bool recursion = false)
|
||||
{
|
||||
// 为了安全,清空一次
|
||||
memset(this, 0, sizeof(this[0]));
|
||||
|
||||
MsgType = 1;
|
||||
HardType = 1;
|
||||
HardLength = 6;
|
||||
Hops = 0;
|
||||
TransID = __REV(dhcpid);
|
||||
Flags = 0x80; // 从0-15bits,最左一bit为1时表示server将以广播方式传送封包给 client,其余尚未使用
|
||||
SetMagic();
|
||||
|
||||
// if(recursion) Prev()->Init(recursion);
|
||||
}
|
||||
|
||||
uint Size() { return sizeof(this[0]); }
|
||||
// uint Offset() { return Prev()->Offset() + Size(); }
|
||||
// UDP_HEADER* Prev() { return (UDP_HEADER*)((byte*)this - sizeof(UDP_HEADER)); }
|
||||
byte* Next() { return (byte*)this + Size(); }
|
||||
|
||||
void SetMagic() { Magic = 0x63538263; }
|
||||
bool Valid() { return Magic == 0x63538263; }
|
||||
}DHCP_HEADER;
|
||||
|
||||
// DHCP后面可选数据格式为“代码+长度+数据”
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DHCP_OPT_Mask = 1,
|
||||
DHCP_OPT_Router = 3,
|
||||
DHCP_OPT_TimeServer = 4,
|
||||
DHCP_OPT_NameServer = 5,
|
||||
DHCP_OPT_DNSServer = 6,
|
||||
DHCP_OPT_LOGServer = 7,
|
||||
DHCP_OPT_HostName = 12,
|
||||
DHCP_OPT_MTU = 26, // 0x1A
|
||||
DHCP_OPT_StaticRout = 33, // 0x21
|
||||
DHCP_OPT_ARPCacheTimeout = 35, // 0x23
|
||||
DHCP_OPT_NTPServer = 42, // 0x2A
|
||||
DHCP_OPT_RequestedIP = 50, // 0x32
|
||||
DHCP_OPT_IPLeaseTime = 51, // 0x33
|
||||
DHCP_OPT_MessageType = 53, // 0x35
|
||||
DHCP_OPT_DHCPServer = 54, // 0x36
|
||||
DHCP_OPT_ParameterList = 55, // 0x37
|
||||
DHCP_OPT_Message = 56, // 0x38
|
||||
DHCP_OPT_MaxMessageSize = 57, // 0x39
|
||||
DHCP_OPT_Vendor = 60, // 0x3C
|
||||
DHCP_OPT_ClientIdentifier = 61, // 0x3D
|
||||
DHCP_OPT_End = 255,
|
||||
}DHCP_OPTION;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DHCP_TYPE_Discover = 1,
|
||||
DHCP_TYPE_Offer = 2,
|
||||
DHCP_TYPE_Request = 3,
|
||||
DHCP_TYPE_Decline = 4,
|
||||
DHCP_TYPE_Ack = 5,
|
||||
DHCP_TYPE_Nak = 6,
|
||||
DHCP_TYPE_Release = 7,
|
||||
DHCP_TYPE_Inform = 8,
|
||||
}DHCP_MSGTYPE;
|
||||
|
||||
typedef struct _DHCP_OPT
|
||||
{
|
||||
DHCP_OPTION Option; // 代码
|
||||
byte Length; // 长度
|
||||
byte Data; // 数据
|
||||
|
||||
struct _DHCP_OPT* Next() { return (struct _DHCP_OPT*)((byte*)this + 2 + Length); }
|
||||
|
||||
struct _DHCP_OPT* SetType(DHCP_MSGTYPE type)
|
||||
{
|
||||
Option = DHCP_OPT_MessageType;
|
||||
Length = 1;
|
||||
Data = type;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
struct _DHCP_OPT* SetData(DHCP_OPTION option, ByteArray& bs)
|
||||
{
|
||||
Option = option;
|
||||
Length = bs.Length();
|
||||
bs.CopyTo(&Data);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
struct _DHCP_OPT* SetData(DHCP_OPTION option, String& str)
|
||||
{
|
||||
ByteArray bs(str);
|
||||
return SetData(option, bs);
|
||||
}
|
||||
|
||||
struct _DHCP_OPT* SetData(DHCP_OPTION option, uint value)
|
||||
{
|
||||
Option = option;
|
||||
Length = 4;
|
||||
memcpy(&Data, (byte*)&value, Length);
|
||||
// 需要考虑地址对齐问题,只有4字节对齐,才可以直接使用整数赋值
|
||||
//*(uint*)&Data = value;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
struct _DHCP_OPT* SetClientId(MacAddress& mac)
|
||||
{
|
||||
Option = DHCP_OPT_ClientIdentifier;
|
||||
Length = 1 + 6;
|
||||
Data = 1; // 类型ETHERNET=1
|
||||
memcpy(&Data + 1, &mac.Value, 6);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
struct _DHCP_OPT* End()
|
||||
{
|
||||
Option = DHCP_OPT_End;
|
||||
|
||||
return this;
|
||||
}
|
||||
}DHCP_OPT;
|
||||
|
||||
#pragma pack(pop) // 恢复对齐状态
|
||||
|
||||
|
||||
Dhcp::Dhcp(W5500 * host)
|
||||
{
|
||||
assert_ptr(host);
|
||||
_w5500 = host;
|
||||
_w5500 -> = IPAddress(0, 0, 0, 0);
|
||||
_UdpPort = new UdpClient(host);
|
||||
|
||||
_UdpPort->Local.Port = 68;
|
||||
_UdpPort->Remote.Port = 67;
|
||||
_UdpPort->Remote.Address = IPAddress::Broadcast();
|
||||
|
||||
Running = false;
|
||||
Result = false;
|
||||
ExpiredTime = 10;
|
||||
|
||||
OnStop = NULL;
|
||||
}
|
||||
|
||||
//Dhcp::Dhcp(TinyIP* tip) : UdpSocket(tip)
|
||||
//{
|
||||
// Type = IP_UDP;
|
||||
// Local.Port = 68;
|
||||
// Remote.Port = 67;
|
||||
// Remote.Address = IPAddress::Broadcast();
|
||||
//
|
||||
// Running = false;
|
||||
// Result = false;
|
||||
// ExpiredTime = 10;
|
||||
//
|
||||
// OnStop = NULL;
|
||||
//}
|
||||
|
||||
void Dhcp::SendDhcp(DHCP_HEADER& dhcp, uint len)
|
||||
{
|
||||
byte* p = dhcp.Next();
|
||||
if(p[len - 1] != DHCP_OPT_End)
|
||||
{
|
||||
// 此时指向的是负载数据后的第一个字节,所以第一个opt不许Next
|
||||
DHCP_OPT* opt = (DHCP_OPT*)(p + len);
|
||||
opt = opt->SetClientId(_w5500->Mac);
|
||||
if(!_w5500->IP.IsAny())
|
||||
opt = opt->Next()->SetData(DHCP_OPT_RequestedIP, _w5500->IP.Value);
|
||||
|
||||
// 构造产品名称,把ID第一个字节附到最后
|
||||
String name;
|
||||
name += "WSWL_SmartOS_"; // 产生拷贝效果
|
||||
name.Append(Sys.ID[0]);
|
||||
|
||||
opt = opt->Next()->SetData(DHCP_OPT_HostName, name);
|
||||
String vendor = "http://www.NewLifeX.com";
|
||||
opt = opt->Next()->SetData(DHCP_OPT_Vendor, vendor);
|
||||
byte ps[] = { 0x01, 0x06, 0x03, 0x2b}; // 需要参数 Mask/DNS/Router/Vendor
|
||||
ByteArray bs(ps, ArrayLength(ps));
|
||||
opt = opt->Next()->SetData(DHCP_OPT_ParameterList, bs);
|
||||
opt = opt->Next()->End();
|
||||
|
||||
len = (byte*)opt + 1 - p;
|
||||
}
|
||||
|
||||
//memcpy(dhcp->ClientMac, (byte*)&_w5500->Mac.Value, 6);
|
||||
for(int i=0; i<6; i++)
|
||||
dhcp.ClientMac[i] = _w5500->Mac[i];
|
||||
|
||||
//RemoteIP = IPAddress::Broadcast;
|
||||
|
||||
Send(*dhcp.Prev(), sizeof(DHCP_HEADER) + len, Remote.Address, Remote.Port, false);
|
||||
}
|
||||
|
||||
// 获取选项,返回数据部分指针
|
||||
DHCP_OPT* GetOption(byte* p, int len, DHCP_OPTION option)
|
||||
{
|
||||
byte* end = p + len;
|
||||
while(p < end)
|
||||
{
|
||||
byte opt = *p++;
|
||||
byte len = *p++;
|
||||
if(opt == DHCP_OPT_End) return 0;
|
||||
if(opt == option) return (DHCP_OPT*)(p - 2);
|
||||
|
||||
p += len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 找服务器
|
||||
void Dhcp::Discover(DHCP_HEADER& dhcp)
|
||||
{
|
||||
byte* p = dhcp.Next();
|
||||
DHCP_OPT* opt = (DHCP_OPT*)p;
|
||||
opt->SetType(DHCP_TYPE_Discover);
|
||||
|
||||
SendDhcp(dhcp, (byte*)opt->Next() - p);
|
||||
}
|
||||
|
||||
void Dhcp::Request(DHCP_HEADER& dhcp)
|
||||
{
|
||||
byte* p = dhcp.Next();
|
||||
DHCP_OPT* opt = (DHCP_OPT*)p;
|
||||
opt->SetType(DHCP_TYPE_Request);
|
||||
|
||||
opt = opt->Next()->SetData(DHCP_OPT_DHCPServer, _w5500->DHCPServer.Value);
|
||||
|
||||
// 发往DHCP服务器
|
||||
SendDhcp(dhcp, (byte*)opt->Next() - p);
|
||||
}
|
||||
|
||||
void Dhcp::PareOption(Stream& ms)
|
||||
{
|
||||
while(ms.Remain())
|
||||
{
|
||||
byte opt = ms.Read<byte>();
|
||||
if(opt == DHCP_OPT_End) break;
|
||||
byte len = ms.Read<byte>();
|
||||
// 有些家用路由器会发送错误的len,大于4字节,导致覆盖前后数据
|
||||
switch(opt)
|
||||
{
|
||||
case DHCP_OPT_Mask: _w5500->Mask = ms.Read<int>(); len -= 4; break;
|
||||
case DHCP_OPT_DNSServer: _w5500->DNSServer = ms.Read<int>(); len -= 4; break;
|
||||
case DHCP_OPT_Router: _w5500->Gateway = ms.Read<int>(); len -= 4; break;
|
||||
case DHCP_OPT_DHCPServer: _w5500->DHCPServer = ms.Read<int>(); len -= 4; break;
|
||||
//default:
|
||||
// debug_printf("Unkown DHCP Option=%d Length=%d\r\n", opt, len);
|
||||
}
|
||||
// DNS可能有多个IP,就不止4长度了
|
||||
if(len > 0) ms.Seek(len);
|
||||
}
|
||||
}
|
||||
|
||||
void RenewDHCP(void* param)
|
||||
{
|
||||
TinyIP* tip = (TinyIP*)param;
|
||||
if(tip)
|
||||
{
|
||||
/*Dhcp dhcp(tip);
|
||||
dhcp.Start();*/
|
||||
// 不能使用栈分配,因为是异步操作
|
||||
Dhcp* dhcp = new Dhcp(tip);
|
||||
dhcp->Start();
|
||||
}
|
||||
}
|
||||
|
||||
void Dhcp::Start()
|
||||
{
|
||||
_expiredTime = Time.Current() + ExpiredTime * 1000000;
|
||||
dhcpid = (uint)Time.Current();
|
||||
|
||||
debug_printf("Dhcp::Start ExpiredTime=%ds DhcpID=0x%08x\r\n", ExpiredTime, dhcpid);
|
||||
|
||||
// 创建任务,每秒发送一次Discover
|
||||
//debug_printf("Dhcp发送Discover ");
|
||||
taskID = Sys.AddTask(SendDiscover, this, 0, 1000000, "DHCP");
|
||||
|
||||
// 通过DHCP获取IP期间,关闭Arp响应
|
||||
//_w5500->EnableArp = false;
|
||||
if(_w5500->Arp) _w5500->Arp->Enable = false;
|
||||
|
||||
Running = true;
|
||||
|
||||
Open();
|
||||
}
|
||||
|
||||
void Dhcp::Stop()
|
||||
{
|
||||
Close();
|
||||
|
||||
Running = false;
|
||||
if(taskID)
|
||||
{
|
||||
debug_printf("Dhcp发送Discover ");
|
||||
Sys.RemoveTask(taskID);
|
||||
}
|
||||
taskID = 0;
|
||||
|
||||
// 通过DHCP获取IP期间,关闭Arp响应
|
||||
//_w5500->EnableArp = true;
|
||||
if(_w5500->Arp) _w5500->Arp->Enable = true;
|
||||
|
||||
debug_printf("Dhcp::Stop Result=%d DhcpID=0x%08x\r\n", Result, dhcpid);
|
||||
|
||||
if(Result) _w5500->ShowInfo();
|
||||
|
||||
if(OnStop) OnStop(this, NULL);
|
||||
|
||||
// 销毁自己
|
||||
delete this;
|
||||
}
|
||||
|
||||
void Dhcp::SendDiscover(void* param)
|
||||
{
|
||||
Dhcp* _dhcp = (Dhcp*)param;
|
||||
if(!_dhcp->Running) return;
|
||||
|
||||
// 检查总等待时间
|
||||
if(_dhcp->_expiredTime < Time.Current())
|
||||
{
|
||||
_dhcp->Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
byte buf[/*sizeof(ETH_HEADER) + sizeof(IP_HEADER) + sizeof(UDP_HEADER) + */sizeof(DHCP_HEADER) + 100];
|
||||
Stream ms(buf, ArrayLength(buf));
|
||||
//ms.Seek(sizeof(ETH_HEADER) + sizeof(IP_HEADER) + sizeof(UDP_HEADER));
|
||||
|
||||
DHCP_HEADER* dhcp = ms.Retrieve<DHCP_HEADER>();
|
||||
|
||||
// 向DHCP服务器广播
|
||||
debug_printf("DHCP::Discover...\r\n");
|
||||
// dhcp->Init(_dhcp->dhcpid, true);
|
||||
|
||||
_dhcp->Discover(*dhcp);
|
||||
}
|
||||
|
||||
void Dhcp::OnProcess(IP_HEADER& ip, UDP_HEADER& udp, Stream& ms)
|
||||
{
|
||||
DHCP_HEADER* dhcp = (DHCP_HEADER*)udp.Next();
|
||||
if(!dhcp->Valid()) return;
|
||||
|
||||
byte* data = dhcp->Next();
|
||||
uint len = ms.Remain();
|
||||
|
||||
// 获取DHCP消息类型
|
||||
DHCP_OPT* opt = GetOption(data, len, DHCP_OPT_MessageType);
|
||||
if(!opt) return;
|
||||
|
||||
// 所有响应都需要检查事务ID
|
||||
if(__REV(dhcp->TransID) != dhcpid) return;
|
||||
|
||||
IPAddress remote = ip.SrcIP;
|
||||
|
||||
if(opt->Data == DHCP_TYPE_Offer)
|
||||
{
|
||||
_w5500->IP = dhcp->YourIP;
|
||||
Stream optData(dhcp->Next(), len);
|
||||
PareOption(optData);
|
||||
|
||||
// 向网络宣告已经确认使用哪一个DHCP服务器提供的IP地址
|
||||
// 这里其实还应该发送ARP包确认IP是否被占用,如果被占用,还需要拒绝服务器提供的IP,比较复杂,可能性很低,暂时不考虑
|
||||
#if NET_DEBUG
|
||||
debug_printf("DHCP::Offer IP:");
|
||||
_w5500->IP.Show();
|
||||
debug_printf(" From ");
|
||||
remote.Show();
|
||||
debug_printf("\r\n");
|
||||
#endif
|
||||
|
||||
// 独立分配缓冲区进行操作,避免数据被其它线程篡改
|
||||
byte buf[sizeof(ETH_HEADER) + sizeof(IP_HEADER) + sizeof(UDP_HEADER) + sizeof(DHCP_HEADER) + 100];
|
||||
Stream ms(buf, ArrayLength(buf));
|
||||
ms.Seek(sizeof(ETH_HEADER) + sizeof(IP_HEADER) + sizeof(UDP_HEADER));
|
||||
|
||||
DHCP_HEADER* dhcp2 = ms.Retrieve<DHCP_HEADER>();
|
||||
|
||||
dhcp2->Init(dhcpid, true);
|
||||
Request(*dhcp2);
|
||||
}
|
||||
else if(opt->Data == DHCP_TYPE_Ack)
|
||||
{
|
||||
_w5500->IP = dhcp->YourIP;
|
||||
#if NET_DEBUG
|
||||
debug_printf("DHCP::Ack IP:");
|
||||
IPAddress(dhcp->YourIP).Show();
|
||||
debug_printf(" From ");
|
||||
remote.Show();
|
||||
debug_printf("\r\n");
|
||||
#endif
|
||||
|
||||
//if(dhcp->YourIP == _w5500->IP)
|
||||
{
|
||||
// 查找租约时间,提前续约
|
||||
opt = GetOption(data, len, DHCP_OPT_IPLeaseTime);
|
||||
if(opt)
|
||||
{
|
||||
// 续约时间,大字节序,时间单位秒
|
||||
uint time = __REV(*(uint*)&opt->Data);
|
||||
|
||||
debug_printf("DHCP IPLeaseTime:%ds\r\n", time);
|
||||
|
||||
// DHCP租约过了一半以后重新获取IP地址
|
||||
if(time > 0)
|
||||
{
|
||||
//debug_printf("Dhcp过期获取 ");
|
||||
Sys.AddTask(RenewDHCP, _w5500, (ulong)time / 2 * 1000000, -1, "DHCP超时");
|
||||
}
|
||||
}
|
||||
|
||||
//return true;
|
||||
Result = true;
|
||||
// 完成任务
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
#if NET_DEBUG
|
||||
else if(opt->Data == DHCP_TYPE_Nak)
|
||||
{
|
||||
// 导致Nak的原因
|
||||
opt = GetOption(data, len, DHCP_OPT_Message);
|
||||
debug_printf("DHCP::Nak IP:");
|
||||
_w5500->IP.Show();
|
||||
debug_printf(" From ");
|
||||
remote.Show();
|
||||
if(opt)
|
||||
{
|
||||
debug_printf(" ");
|
||||
Sys.ShowString(&opt->Data, opt->Length);
|
||||
}
|
||||
debug_printf("\r\n");
|
||||
}
|
||||
else
|
||||
debug_printf("DHCP::Unkown Type=%d\r\n", opt->Data);
|
||||
#endif
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
#ifndef _TinyIP_DHCP_H_
|
||||
#define _TinyIP_DHCP_H_
|
||||
|
||||
#include "Udp.h"
|
||||
/*
|
||||
// DHCP协议
|
||||
class Dhcp : public UdpSocket
|
||||
{
|
||||
private:
|
||||
uint dhcpid;
|
||||
uint taskID;
|
||||
ulong _expiredTime;
|
||||
ulong _nextTime;
|
||||
|
||||
void Discover(DHCP_HEADER& dhcp);
|
||||
void Request(DHCP_HEADER& dhcp);
|
||||
void PareOption(Stream& bs);
|
||||
|
||||
void SendDhcp(DHCP_HEADER& dhcp, uint len);
|
||||
|
||||
static void SendDiscover(void* param);
|
||||
public:
|
||||
bool Running; // 正在运行
|
||||
bool Result; // 是否获取IP成功
|
||||
uint ExpiredTime; // 过期时间
|
||||
|
||||
Dhcp(TinyIP* tip);
|
||||
|
||||
void Start(); // 开始
|
||||
void Stop(); // 停止
|
||||
|
||||
EventHandler OnStop;
|
||||
|
||||
protected:
|
||||
virtual void OnProcess(IP_HEADER& ip, UDP_HEADER& udp, Stream& ms);
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class Dhcp
|
||||
{
|
||||
Dhcp(W5500 * host);
|
||||
public:
|
||||
DHCP_HEADER * dhcpdata;
|
||||
|
||||
private:
|
||||
W5500 * _w5500;
|
||||
UDPClient * _UdpPort;
|
||||
|
||||
uint dhcpid;
|
||||
uint taskID;
|
||||
ulong _expiredTime;
|
||||
ulong _nextTime;
|
||||
|
||||
void Discover(DHCP_HEADER& dhcp);
|
||||
void Request(DHCP_HEADER& dhcp);
|
||||
void PareOption(Stream& bs);
|
||||
|
||||
void SendDhcp(DHCP_HEADER& dhcp, uint len);
|
||||
|
||||
static void SendDiscover(void* param);
|
||||
public:
|
||||
bool Running; // 正在运行
|
||||
bool Result; // 是否获取IP成功
|
||||
uint ExpiredTime; // 过期时间
|
||||
|
||||
Dhcp(TinyIP* tip);
|
||||
|
||||
void Start(); // 开始
|
||||
void Stop(); // 停止
|
||||
|
||||
EventHandler OnStop;
|
||||
|
||||
protected:
|
||||
virtual void OnProcess(IP_HEADER& ip, UDP_HEADER& udp, Stream& ms);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,12 +0,0 @@
|
|||
#include "Tcp.h"
|
||||
|
||||
#define NET_DEBUG 0
|
||||
//#define NET_DEBUG DEBUG
|
||||
|
||||
|
||||
/*
|
||||
三次握手过程:
|
||||
A=>B SYN
|
||||
B=>A SYN+ACK
|
||||
A=>B ACK
|
||||
*/
|
|
@ -1,65 +0,0 @@
|
|||
#ifndef _TinyIP_TCP_H_
|
||||
#define _TinyIP_TCP_H_
|
||||
|
||||
#include "W5500.h"
|
||||
|
||||
// Tcp会话
|
||||
class TcpSocket : public HardwareSocket, public ITransport
|
||||
{
|
||||
public:
|
||||
// Tcp状态
|
||||
typedef enum
|
||||
{
|
||||
Closed = 0,
|
||||
SynSent = 1,
|
||||
SynAck = 2,
|
||||
Established = 3,
|
||||
}TCP_STATUS;
|
||||
|
||||
ushort Port; // 本地端口,接收该端口数据包。0表示接收所有端口的数据包
|
||||
ushort BindPort; // 绑定端口,用于发出数据包的源端口。默认为Port,若Port为0,则从1024算起,累加
|
||||
IPEndPoint Remote; // 远程地址。默认发送数据的目标地址
|
||||
IPEndPoint Local; // 本地地址
|
||||
|
||||
TCP_STATUS Status; // 状态
|
||||
|
||||
TCP_HEADER* Header;
|
||||
|
||||
TcpSocket(W5500* pw5500):HardwareSocket(pw5500);
|
||||
|
||||
// 处理数据包
|
||||
virtual bool Process(IP_HEADER& ip, Stream& ms);
|
||||
|
||||
bool Connect(IPAddress& ip, ushort port); // 连接远程服务器,记录远程服务器IP和端口,后续发送数据和关闭连接需要
|
||||
bool Send(ByteArray& bs); // 向Socket发送数据,可能是外部数据包
|
||||
bool Disconnect(); // 关闭Socket
|
||||
|
||||
// 收到Tcp数据时触发,传递结构体和负载数据长度。返回值指示是否向对方发送数据包
|
||||
typedef bool (*TcpHandler)(TcpSocket& socket, TCP_HEADER& tcp, byte* buf, uint len);
|
||||
TcpHandler OnAccepted;
|
||||
TcpHandler OnReceived;
|
||||
TcpHandler OnDisconnected;
|
||||
|
||||
virtual string ToString();
|
||||
|
||||
protected:
|
||||
void SendAck(uint len);
|
||||
|
||||
void SetSeqAck(TCP_HEADER& tcp, uint ackNum, bool cp_seq);
|
||||
void SetMss(TCP_HEADER& tcp);
|
||||
bool Send(TCP_HEADER& tcp, uint len, byte flags);
|
||||
|
||||
virtual void OnProcess(TCP_HEADER& tcp, Stream& ms);
|
||||
virtual void OnAccept(TCP_HEADER& tcp, uint len);
|
||||
virtual void OnAccept3(TCP_HEADER& tcp, uint len);
|
||||
virtual void OnDataReceive(TCP_HEADER& tcp, uint len);
|
||||
virtual void OnDisconnect(TCP_HEADER& tcp, uint len);
|
||||
|
||||
virtual bool OnOpen();
|
||||
virtual void OnClose();
|
||||
|
||||
virtual bool OnWrite(const byte* buf, uint len);
|
||||
virtual uint OnRead(byte* buf, uint len);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,4 +0,0 @@
|
|||
#include "Udp.h"
|
||||
|
||||
//#define NET_DEBUG DEBUG
|
||||
#define NET_DEBUG 0
|
|
@ -1,43 +0,0 @@
|
|||
#ifndef _TinyIP_UDP_H_
|
||||
#define _TinyIP_UDP_H_
|
||||
|
||||
#include "W5500.h"
|
||||
|
||||
// Udp会话
|
||||
class UdpSocket : public Socket, public ITransport
|
||||
{
|
||||
private:
|
||||
|
||||
public:
|
||||
ushort Port; // 本地端口,接收该端口数据包。0表示接收所有端口的数据包
|
||||
ushort BindPort; // 绑定端口,用于发出数据包的源端口。默认为Port,若Port为0,则从1024算起,累加
|
||||
IPEndPoint Remote; // 远程地址。默认发送数据的目标地址
|
||||
IPEndPoint CurRemote; // 远程地址。本次收到数据的远程地址
|
||||
IPEndPoint CurLocal; // 本地地址
|
||||
|
||||
UdpSocket(W5500* pw5500):HardwareSocket(pw5500);
|
||||
|
||||
// 处理数据包
|
||||
virtual bool Process(IP_HEADER& ip, Stream& ms);
|
||||
|
||||
// 收到Udp数据时触发,传递结构体和负载数据长度。返回值指示是否向对方发送数据包
|
||||
typedef bool (*UdpHandler)(UdpSocket& socket, UDP_HEADER& udp, IPEndPoint& remote, Stream& ms);
|
||||
UdpHandler OnReceived;
|
||||
|
||||
// 发送UDP数据到目标地址
|
||||
void Send(ByteArray& bs, IPAddress ip = IPAddress::Any, ushort port = 0);
|
||||
|
||||
virtual string ToString();
|
||||
|
||||
protected:
|
||||
void Send(UDP_HEADER& udp, uint len, IPAddress& ip, ushort port, bool checksum = true);
|
||||
virtual void OnProcess(IP_HEADER& ip, UDP_HEADER& udp, Stream& ms);
|
||||
|
||||
virtual bool OnOpen();
|
||||
virtual void OnClose();
|
||||
|
||||
virtual bool OnWrite(const byte* buf, uint len);
|
||||
virtual uint OnRead(byte* buf, uint len);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -462,7 +462,12 @@ void TokenController::ShowStat()
|
|||
{
|
||||
ByteArray bs(str);
|
||||
//debug_printf("握手广播 ");
|
||||
udp->Send(bs, IPAddress::Broadcast(), 514);
|
||||
//udp->Send(bs, IPAddress::Broadcast(), 514);
|
||||
IPEndPoint ep = udp->Remote;
|
||||
udp->Remote.Port = 514;
|
||||
udp->Remote.Address = IPAddress::Broadcast();
|
||||
udp->Send(bs);
|
||||
udp->Remote = ep;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue