void broadcast(BufferRef buf, client* from=NULL, bool system_msg=false)
{
	//if(system_msg) while(buf.Length>0 && buf.Data[buf.Length-1]=='\n')buf.Length--;
	const BufferRef* tmp=&buf;
	if(from!=NULL || system_msg)
	{
		StringBuilder sb;
		if(system_msg)
			sb << "\x1B[41;1;33m";
		if(from!=NULL)
		{
			if(from->name_init)
				sb << from->name << " (";
			sb << from->ep->ToStr();
			if(from->name_init)
				sb << ')';
			sb << ": ";
		}
		sb << buf;
		if(system_msg) sb << "\x1B[0;0;0m\n";
		Buffer* tmpb=new Buffer(sb.ToBuffer());
		tmp=tmpb;
	}
	StandardStream().Write(*tmp);
	for(auto it=clients.begin();it!=clients.end();it++)
	{
		if((*it)!=from && (*it)->name_init)
			(*it)->send(*tmp);
	}
}
void DNSServer::sendreply(const EndPoint& ep, const dnsreq& response)
{
	StringBuilder sb;
	create_dns_packet(response, sb);
	boost::shared_ptr<EndPoint> ep1 = boost::shared_ptr<EndPoint>(
			EndPoint::CreateNull(ep.AddressFamily));
	ep.Clone(*ep1.get());
	q.Append(
	{ ep1, sb.ToBuffer() });
	q.start();
}
int main()
{
	/*
	IPEndPoint ep(IPAddress("0.0.0.0"),26969);
	Socket s(AF_INET,SOCK_DGRAM,0);
	s.Bind(ep);
	Buffer b(4096);
	StandardStream ss;
	while(true)
	{
		int br=s.Recv(b);
		ss << b.SubBuffer(0,br);
	}
	//*/
	/*IPEndPoint ep(IPAddress("0.0.0.0"),7899);
	Socket s1(AF_INET,SOCK_STREAM,0);
	s1.Bind(ep);
	s1.Listen(10);
	while(true)
	{
		Socket s=s1.Accept();
		try{
			Buffer b(4096);
			StandardStream ss;
			while(true)
			{
				int br=s.Recv(b);
				if(br<=0)break;
				ss << b.SubBuffer(0,br);
			}
		}catch(Exception&ex){
			s.Close();
		}
	}*/
	StringBuilder motd_sb;
	Buffer motd;
	motd_sb << "You are now connected to the chat server.\n";
	try
	{
		FileStream fs("motd",O_RDONLY);
		motd_sb.Clear();
		while(motd_sb.Append(fs,4096)>0);
	}
	catch(Exception& ex){}
	motd_sb << "Please enter a nickname: ";
	motd=motd_sb.ToBuffer();
	IPEndPoint ep(IPAddress("0.0.0.0"),16969);
	Socket s1(AF_INET,SOCK_STREAM,0);
	s1.Bind(ep);
	s1.Listen(10);
	SocketManager* m = SocketManager::GetDefault();
	struct
	{
		SocketManager::Callback cb;
	} tmp1;
	tmp1.cb=SocketManager::Callback([&](void* v, SocketManager* m, Socket sock)
	{
		Socket s=sock.Accept();
		client* zxcv=new client(s);
		zxcv->send(motd);
		broadcast("Connected", zxcv, true);
		clients.insert(zxcv);
		zxcv->cb=SocketManager::Callback([](void* v, SocketManager* m, Socket sock)
		{
			client* zxcv=(client*)v;
			//try
			//{
				int br;
				if((br=m->EndRecv(sock))<=0)goto close;
				if(zxcv->name_init)
					broadcast(zxcv->b.SubBuffer(0,br), zxcv);
				else
				{
					if(br>50)
					{
						zxcv->send("\x1B[41;1;33mNickname can not be longer than 50 chars.\x1B[0;0;0m\nEnter a new one: ");
						goto aaaaa;
					}
					BufferRef tmp=strip_newline(zxcv->b.SubBuffer(0,br));
					zxcv->name=string((char*)tmp.Data,tmp.Length);
					zxcv->name_init=true;
					broadcast("Set name", zxcv, true);
					StringBuilder sb;
					sb << "List of users (";
					sb << (int)(clients.size()-1);
					sb << "): \n";
					for(auto it=clients.begin();it!=clients.end();it++)
					{
						if((*it)!=zxcv)
						{
							if((*it)->name_init)
								sb << (*it)->name << " (";
							sb << (*it)->ep->ToStr();
							if((*it)->name_init)
								sb << ')';
							sb << '\n';
						}
					}
					sb << "You can now chat.\n";
					zxcv->send(sb.ToBuffer());
				}
			aaaaa:
				m->BeginRecv(sock, zxcv->b, zxcv->cb, false);
			//}catch(Exception& ex){goto close;}
			return;
		close:
			m->Cancel(sock);
			sock.Close();
			clients.erase(zxcv);
			broadcast("Disconnected", zxcv, true);
			delete zxcv;
		}, zxcv);
		m->BeginRecv(s, zxcv->b, zxcv->cb, false);
		m->BeginAccept(sock, tmp1.cb);
	});
	m->BeginAccept(s1, tmp1.cb);
	m->EventLoop();
}