Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


Winsock -> Connection

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General programming
View previous topic :: View next topic  
Author Message
iPromise
Grandmaster Cheater
Reputation: -1

Joined: 27 Jun 2009
Posts: 529
Location: Canada

PostPosted: Tue Jul 20, 2010 3:34 pm    Post subject: Winsock -> Connection Reply with quote

I can make a fine connection with myself, using localhost / 127.0.0.1. But whenever I put my external ip address and port, it fails to bind() and won't connect?

Here is my code:

Code:

#include <WinSock2.h>

#include <iostream>

#include <string>

using namespace std;

void Host ( void )
{
   WSADATA WSAData;

   WSAStartup(MAKEWORD(2, 0), &WSAData);

   if ( WSAData.wVersion >= 2 )
   {
      cout << "Success: Your Winsock version is compatible with the software." << endl;
   }
   else
   {
      cout << "Error: Your Winsock version isn't compatible with the software." << endl;
   }

   SOCKET Socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );

   int Connectivity;

   sockaddr_in sockaddr;

   sockaddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
   sockaddr.sin_family           = AF_INET;
   sockaddr.sin_port             = htons(8888);

   Connectivity = bind(Socket, (LPSOCKADDR) &sockaddr, sizeof(sockaddr));

   if ( Connectivity == SOCKET_ERROR )
   {
      cout << "Error: Failed to bind the socket with the 'sockaddr' structure." << endl;
   }
   else
   {
      cout << "Success: Successfully binded the socket with the 'sockaddr' structure." << endl;
   }

   SOCKET Client = INVALID_SOCKET;

   while ( Client == INVALID_SOCKET )
   {
      Connectivity = listen(Socket, 10);

      if ( Connectivity == SOCKET_ERROR )
      {
         cout << "Error: Failed to listen to connections." << endl;
      }
      else
      {
         cout << "Success: Successfully listening to connections." << endl;
      }

      Client = accept(Socket, NULL, NULL);

      if ( Client == INVALID_SOCKET )
      {
         cout << "Error: No connectivity from 'Client'.\n\n" << endl;
      }
      else
      {
         cout << "Success: Connectivity from 'Client'.\n\n" << endl;
      }

      Sleep(1000);
   }

   // Send and receive messages

   bool Session = false;

   while ( !Session )
   {
      string Message;

      cout << endl << "Send Message: "; cin >> Message; cout << endl;

      send( Client, Message.c_str(), Message.length(), 0 );

      char Buffer[500] = {0};

      recv( Client, Buffer, 500, 0 );

      cout << "User sent: " << Buffer << endl;

      if ( !strcmp(Message.c_str(), "quit") )
      {
         Session = true;
      }

      Sleep(100);
   }

   closesocket(Client);
   closesocket(Socket);

   WSACleanup();
}
void Join ( void )
{
   WSADATA WSAData;

   WSAStartup(MAKEWORD(2, 0), &WSAData);

   if ( WSAData.wVersion >= 2 )
   {
      cout << "Success: Your Winsock version is compatible with the software." << endl;
   }
   else
   {
      cout << "Error: Your Winsock version isn't compatible with the software." << endl;
   }

   SOCKET Socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );

   sockaddr_in sockaddr;

   sockaddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
   sockaddr.sin_family           = AF_INET;
   sockaddr.sin_port             = htons(8888);

   int Connectivity = INVALID_SOCKET;

   while ( Connectivity == INVALID_SOCKET )
   {
      Connectivity = connect( Socket, (LPSOCKADDR) &sockaddr, sizeof(sockaddr) );

      if ( Connectivity == INVALID_SOCKET )
      {
         cout << "Error: Failed to connect." << endl;
      }
      else
      {
         cout << "Success: Connected successfully." << endl;
      }

      Sleep(1000);
   }

   // Send and receive messages

   bool Session = false;

   while ( !Session )
   {
      string Message;

      cout << endl << "Send Message: "; cin >> Message; cout << endl;

      send( Socket, Message.c_str(), Message.length(), 0 );

      char Buffer[500] = {0};

      recv( Socket, Buffer, 500, 0 );

      cout << "User sent: " << Buffer << endl;

      if ( !strcmp(Message.c_str(), "quit") )
      {
         Session = true;
      }

      Sleep(100);
   }

   closesocket(Socket);
}

void main ( void )
{
   system("TITLE C++ - Winsock");
   system("COLOR 3");

   int Choice = 0;

   cout << "1) Host server\n";
   cout << "2) Join server\n";

   cout << endl << "Choose: "; cin >> Choice; cout << endl;

   if ( Choice == 1 )
   {
      Host();
   }
   else if ( Choice == 2 )
   {
      Join();
   }
}
Back to top
View user's profile Send private message MSN Messenger
Rur3k
Expert Cheater
Reputation: 0

Joined: 19 Aug 2008
Posts: 235
Location: HaHaVille Maryland

PostPosted: Tue Jul 20, 2010 3:37 pm    Post subject: Reply with quote

Example.cpp
Code:
#include "NetworkEngine.h"

// Server
NetworkEngine *server;
Message Datas = {   "E.M.M.Y",
               "Hello there!",
               1};


// Client
NetworkEngine *Client;
Message test;




int RunServer()
{
   cout << "ServerMsg: Booting...\n";
   server = new NetworkEngine(7700);
   //
   for(int x=0; x<server->GetTotalConnected(); x++)
   {
      cout << "Current Values: " << ID[x] << endl;
   }
   //


   if (server->GetMutexHandle() == NULL)
   {
      cout << "ServerMsg: Unable to create mutex.\n";
      server->EndServer();
      return 1;
   }



   if (server->GetThreadHandle() == NULL)
   {
      cout << "ServerMsg: Unable to start accepting.\n";
      server->EndServer();
      return 1;
   }

   Sleep(100);
   
   //
   ///
   ////
   server->GoListen(Datas);
   ////
   ///
   //
   

   server->EndServer();
   cout << "ServerMsg: Press any key to shut me down....\n";
   getchar();
   return 0;
}

int RunClient()
{

   Client = new NetworkEngine(7700, "71.166.35.96");
   test.ID = 5;

   if (Client->GetSocket() == -1)
   {
      Client->EndClient();
      PostQuitMessage(0);
   }

   char buffer[MAX_SIZE];
   cout << "Client: Type what you want to send, if you want to exit, type 'exit'\n\nClient: > ";
   for (;;)
   {
      cout << "> ";
      gets(test.Data);
      if (strcmp(test.Data, "exit") == 0)
      {
         break;
      }
      if (strcmp(test.Data, "ListC") == 0)
      {
         system("cls");
         cout << "";
      }
      ///**********************************************************
      if(strcmp(test.Data, "color green") == 0)
      {
         system("COLOR FA");
         continue;
      }
      if (strcmp(test.Data, "id") == 0)
      {
         cout << "Client: Change your ID now.\n ";
         gets(buffer);
         test.ID   = atoi(buffer);
         system("cls");
         continue;
      }
      ////
      if (strcmp(test.Data, "SetN") == 0)
      {
         cout << "Client: Change your Name now: ";
         gets(test.Name);
         cout << "Your name is now: " << test.Name;
         system("cls");
         continue;
      }
      ////
      if(strcmp("cls", test.Data) == 0)
      {
         system("cls");
         cout << "Systemia C.I.A operating Correctly.\n";
         continue;
      }
      ///**********************************************************
      Client->SendData(test);
      
   }
   Client->EndClient();
   return 0;
}


bool isaserver = false;
int main()
{
   system("color F0");
   SetConsoleTitleA("Rur3k's chat for us *CODERS*");
   cout << "(*ADMIN ONLY*) Server[1]\nJoin Server[2]\nExit[3]\n\n> ";
   int choice;
   cin >> choice;
   switch(choice)
   {
   case 1:
      isaserver = true;
      return RunServer();
      //system("cls");
      //cout << "You are not an admin, program now shutting down...";
      //Sleep(1500);
      //return 0;
   case 2:
      return RunClient();
   case 3:
      return 0;
   default:
      return 0;
   }
}
//
//
//
// Custom Chat functions, this can be erased if you so desire
//      Send a global message to all clients connected
void SendGlobal(Message msg, SOCKET ClientSocket)
{
   for(int x=0; x<server->GetTotalConnected(); x++)
   {
      cout << "Server Sending to: " << ID[x] << endl;
   }
   for(int x=0; x<server->GetTotalConnected(); x++)
   {
      if(ID[x] != ClientSocket)
      {
         int err = server->SendData(msg, ID[x]);
         if(err == SOCKET_ERROR)
            cout << "Failed to send to client("<<x<<")\n";
      }
   }
}


//
//
//______________________________
//******************************
// Required Handlers
void HandleMessageStruct(Message msg, SOCKET ClientSocket)
{
   if(isaserver)
   {
      if(strcmp("ServerCls", msg.Data) == 0)
      {
         system("cls");
         return;
      }
      SendGlobal(msg, ClientSocket);
   }
      cout << msg.Name << ": " << msg.Data << "\n";
}


NetWorkEngine.cpp
Code:
#include "NetworkEngine.h"
#define FREE -999
SOCKET ID[CLIENT_LIST_SIZE];


SOCKET NetworkEngine::GetNextFreeSlot()
{
   for(int x=0; x<CLIENT_LIST_SIZE; x++)
   {
      if(ID[x] == FREE)
      {
         cout << "ID["<<x<<"] is free.\n";
         return x;
      }
   }
   return CLIENT_LIST_SIZE;
}

int NetworkEngine::AddID(SOCKET socket)
{
   ID[GetNextFreeSlot()] = socket;   // set the clients socket to the next free slot
   TotalConnected++;
   return 0;
}

int NetworkEngine::RemoveID(SOCKET socket)
{
   return 0;
}
//______________________________________________________________
//**************************************************************
//==============================================================
//**************************************************************
//______________________________________________________________




NetworkEngine::NetworkEngine(int Port)
{
   for(int x=0; x<CLIENT_LIST_SIZE; x++)
      ID[x]   = FREE;
   TotalConnected = 0;
   _IsServer   = true;
   ServPort   = Port;
   gQuitFlag   = false;
   waitTime.tv_sec      = 0; // Set it to 0
   waitTime.tv_usec   = 0; // Set it to 0

   FD_ZERO(&masterSet);

   StartServer();
}


int NetworkEngine::StartServer()
{
   Hmutex = CreateMutex(NULL, false, NULL);
   int error;
   if ((error = WSAStartup(MAKEWORD(2, 2), &wsaData)) == SOCKET_ERROR)
   {
      cout << "Server: Winsock failed to start.\n";
      return -1;
   }



   ServSock = socket(AF_INET, SOCK_STREAM, 0);
   if (ServSock == SOCKET_ERROR)
   {
      cout << "Server: Unable to create socket;\n";
      return -1;
   }


   server.sin_family = AF_INET;
   server.sin_port = htons(ServPort);
   server.sin_addr.s_addr = INADDR_ANY;

   if (bind(ServSock, (sockaddr*)&server, sizeof(server)) == SOCKET_ERROR)
   {
      cout << "Server: Binding failed.\n";
      closesocket(ServSock);
      return -1;
   }



   if (listen(ServSock, 5) == SOCKET_ERROR)
   {
      cout << "Server: Listening failed.\n";
      closesocket(ServSock);
      return -1;
   }



   cout << "Server: Systemia C.I.A booted.\n";

   int threadID;
   Hthread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&_threadstartS, this, 0, (LPDWORD)&threadID);
   return 0;
}

int NetworkEngine::_threadstartS(void *param)
{
   ((NetworkEngine*)param)->ServerAcceptingThread();
   return 0;
}

void NetworkEngine::ServerAcceptingThread()
{
   int mySocket = ServSock;

   
   for (;;)
   {
   
      unsigned int clientSocket = accept(mySocket, 0, 0);   

      if (clientSocket == SOCKET_ERROR)
      {
         cout << "!= Unable to accept socket.\n";
         gQuitFlag = true;
         return;
      }
      else
      {
         WaitForSingleObject(Hmutex, INFINITE);
         FD_SET(clientSocket, &masterSet);
         AddID(clientSocket);
         ReleaseMutex(Hmutex);

         
         cout << "!= Client on " << clientSocket <<" connected.\n" << endl;
      }
   }
      return;
   
}

void NetworkEngine::EndServer()
{
   WaitForSingleObject(Hthread, INFINITE);// Kill thread and handle
   CloseHandle(Hthread);
   CloseHandle(Hmutex);
   closesocket(ServSock);
   WSACleanup();
   cout << "!= Shutting down Systemia C.I.A...\n";
}

void NetworkEngine::HoldMutex(bool Hold)
{
   if(Hold)
      WaitForSingleObject(Hmutex, INFINITE);
   else
      ReleaseMutex(Hmutex);
}


void NetworkEngine::GoListen(Message Data)
{
   for (;;)
   {
      if (IsQuit())
      {
         break;
      }

      HoldMutex(true);
      FD_SET TempSet = masterSet;
      HoldMutex(false);

      if (TempSet.fd_count == 0)
      {
         continue;
      }


      int result = select(TempSet.fd_count, &TempSet, NULL, NULL, &waitTime); // Select a socket in out TempSet
      //
      //
      if (result == 0) // Check for 0's agian
      {
         continue; // = Empty
      }
      if (result == SOCKET_ERROR)
      {
         cout << "!= Select Macro has failed.\n";
         continue;
      }

      for (unsigned int i = 0; i < TempSet.fd_count; i++)
      {
         unsigned int clientSocket = TempSet.fd_array[i];

         int nBytes;
         

         unsigned long messageSize;
         nBytes = recv(clientSocket, (char*)&messageSize, sizeof(messageSize), 0);

         if (nBytes == SOCKET_ERROR)
         {
            int error = WSAGetLastError();
            if (error == WSAECONNRESET)
            {
               HoldMutex(true);
               FD_CLR(clientSocket, &masterSet);
               RemoveID(clientSocket);
               HoldMutex(false);            
               closesocket(clientSocket);               
               cout << "!= Client on "<< clientSocket << " has Disconnected." << endl;
               continue;
            }
            else
            {
               cout << "!= Unrecoverable error has occured, shutting down.\n";
               SetQuit(true);
               break;
            }
         }
         if (nBytes == 0)
         {
            HoldMutex(true);
            FD_CLR(clientSocket, &masterSet);
            RemoveID(clientSocket);
            HoldMutex(false);
            closesocket(clientSocket);            
            cout << "!= Client on " << clientSocket << " has disconnected" << "\n";
            Sleep(1000);
            continue;
         }
         messageSize = ntohl(messageSize);
         nBytes = recv(clientSocket, (char*)&Data, messageSize, 0); // buffer
         if (nBytes == SOCKET_ERROR)
         {
            cout << "!= Socket data has errored.\n";
            SetQuit(true);
            EndServer();
         }
         HandleMessageStruct(Data, clientSocket);
      }
   }
}

Message NetworkEngine::ReceiveData(SOCKET socket)
{
   int nBytes;
   Message temp;

   unsigned long messageSize;
   nBytes = recv(socket, (char*)&messageSize, sizeof(messageSize), 0);

   messageSize = ntohl(messageSize);
   nBytes = recv(socket, (char*)&temp, messageSize, 0); // buffer

   return temp;
}
//****************************************************************
//                  CLIENT Functions
//****************************************************************

NetworkEngine::NetworkEngine(unsigned short Port, const char *Address)
{
   StartClient(Port, Address);
}

int NetworkEngine::StartClient(unsigned short port, const char* Address)
{
   int error;
   _IsServer   = false;
   if ((error = WSAStartup(MAKEWORD(2, 2), &Client_wsaData)) == SOCKET_ERROR)
   {
      cout << "Client: Winsock has failed to start up.\n";
      return -1;
   }

   Sock = socket(AF_INET, SOCK_STREAM, 0);

   if (Sock == SOCKET_ERROR)
   {
      cout << "Client: Unable to create a socket.\n";
      return -1;
   }

   if ((host_entry = gethostbyname(Address)) == NULL)
   {
      cout << "Client: Unable to find host.\n";
   }

   client.sin_family = AF_INET;
   client.sin_port = htons(port);
   client.sin_addr.s_addr = *(unsigned long*) host_entry->h_addr;

   if (connect(Sock, (sockaddr*)&client, sizeof(client)) == SOCKET_ERROR)
   {
      cout << "Client: Failed to connect to server.\n";
      return -1;
   }
   cout << "Client: Systemia C.I.A is up and running.\n";

   int threadID;
   Hthread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&_threadstartC, this, 0, (LPDWORD)&threadID);
   return Sock;
}


int NetworkEngine::_threadstartC(void *param)
{
   ((NetworkEngine*)param)->ClientRecvThread();
   return 0;
}


SOCKET   NetworkEngine::SendData(char buffer[])
{
   int nBytes;
   unsigned long messageSize = strlen(buffer);
   messageSize = htonl(messageSize);
   if ((nBytes = send(Sock, (char*)&messageSize, sizeof(messageSize), 0)) == SOCKET_ERROR)
   {
      cout << "Client: Sending data size has failed.\n";
      return SOCKET_ERROR;
   }
   messageSize = ntohl(messageSize);
   if ((nBytes = send(Sock, buffer, messageSize, 0)) == SOCKET_ERROR)
   {
      cout << "Client: Sending data has failed.\n";
      return SOCKET_ERROR;
   }
   cout << "\n>";
   return 0;
}

SOCKET   NetworkEngine::SendData(struct Message Data)
{
   int nBytes;
   unsigned long messageSize = sizeof(Data);
   messageSize = htonl(messageSize);
   if ((nBytes = send(Sock, (char*)&messageSize, sizeof(messageSize), 0)) == SOCKET_ERROR)
   {
      cout << "Client: Sending data size has failed.\n";
      return SOCKET_ERROR;
   }
   messageSize = ntohl(messageSize);
   if ((nBytes = send(Sock, (char*)&Data, messageSize, 0)) == SOCKET_ERROR)
   {
      cout << "Client: Sending data has failed.\n";
      return SOCKET_ERROR;
   }
   cout << "\n>";
   return 0;
}
SOCKET   NetworkEngine::SendData(struct Message Data, SOCKET Socket)
{
   int nBytes;
   unsigned long messageSize = sizeof(Data);
   messageSize = htonl(messageSize);
   if ((nBytes = send(Socket, (char*)&messageSize, sizeof(messageSize), 0)) == SOCKET_ERROR)
   {
      cout << "Client: Sending data size has failed.\n";
      return SOCKET_ERROR;
   }
   messageSize = ntohl(messageSize);
   if ((nBytes = send(Socket, (char*)&Data, messageSize, 0)) == SOCKET_ERROR)
   {
      cout << "Client: Sending data has failed.\n";
      return SOCKET_ERROR;
   }
   cout << "\n>";
   return 0;
}

void NetworkEngine::ClientRecvThread()
{
   for (;;)
   {
      Message temp = ReceiveData(GetSocket());
      HandleMessageStruct(temp, 0);
   }
}

void NetworkEngine::EndClient()
{
   closesocket(Sock);
   WSACleanup();
   cout << "Client: Shutting down.\n";
}


NetworkEngine.h
Code:
#include <winsock2.h>
#include <iostream>
using namespace std;

//#pragma pack
#define MAX_SIZE         512
#define CLIENT_LIST_SIZE   20

// Keeps track of all sockets
extern SOCKET ID[CLIENT_LIST_SIZE];


// Modify this Message Struct as needed
struct Message
{
   char   Name[MAX_SIZE];
   char   Data[MAX_SIZE];
   int      ID;
};

// Required Handlers
void HandleMessageStruct(Message msg, SOCKET socket);
//**************************************


class NetworkEngine
{
private:
   bool      _IsServer;
   int         TotalConnected;
   // Server Variables
   SOCKET      ServSock;
   int         ServPort;
   WSAData      wsaData;
   struct      sockaddr_in server;
   HANDLE      Hthread;
   HANDLE      Hmutex;
   FD_SET      masterSet;
   timeval      waitTime;

   bool      gQuitFlag;

   static int   _threadstartS(void *param);
   static int   _threadstartC(void *param);
   void      ServerAcceptingThread();
   void      ClientRecvThread();

   // Client Variables
   WSAData      Client_wsaData;
   SOCKET      Sock;
   struct      hostent *host_entry;
   struct      sockaddr_in client;

   int         StartClient(unsigned short Port, const char* Address);

public:
   // Constructor SERVER
   NetworkEngine(int Port);
   // Constructor CLIENT
   NetworkEngine(unsigned short Port, const char* Address);


   // SERVER Functions
   int         StartServer();
   SOCKET      GetServSocket()            {   return ServSock;   };
   void      SetServSocket(SOCKET sSock)   {   ServSock = sSock;   };
   HANDLE      GetMutexHandle()         {   return Hmutex;      };
   HANDLE      GetThreadHandle()         {   return Hthread;      };
   void      HoldMutex(bool Hold = false);
   bool      IsQuit()               {   return gQuitFlag;   };
   void      SetQuit(bool Q)            {   gQuitFlag = Q;      };
   void      GoListen(Message Data);
   SOCKET      SendData(struct Message Data, SOCKET Socket);
   void      EndServer();
//   bool      IsServer()               {   return _IsServer;   };


   // CLIENT Functions
   void      EndClient();
   SOCKET      GetSocket()               {   return Sock;   };
   SOCKET      SendData(char DataSize[MAX_SIZE]);
   SOCKET      SendData(struct Message Data);
   Message      ReceiveData(SOCKET socket);

   // Get Next Free ID
   SOCKET      GetNextFreeSlot();
   int         AddID(SOCKET socket);
   int         RemoveID(SOCKET socket);
   int         GetTotalConnected()         {   return TotalConnected;   };
};


I have the same problem. :"(

_________________
*Rur3k's Haven*

_______________________________________
The wise rapper "Chino" once said, "You can't mapquest your life direction"

My BEST super trainer for Hands of War
Back to top
View user's profile Send private message MSN Messenger
HomerSexual
Grandmaster Cheater Supreme
Reputation: 5

Joined: 03 Feb 2007
Posts: 1657

PostPosted: Tue Jul 20, 2010 9:42 pm    Post subject: Reply with quote

check port forwarding if you go through a router
_________________
Back to top
View user's profile Send private message
iPromise
Grandmaster Cheater
Reputation: -1

Joined: 27 Jun 2009
Posts: 529
Location: Canada

PostPosted: Wed Jul 21, 2010 10:05 pm    Post subject: Reply with quote

I port forwarded port: 2300 TCP/UDP, I try to connect and I still get an error.
Back to top
View user's profile Send private message MSN Messenger
tombana
Master Cheater
Reputation: 2

Joined: 14 Jun 2007
Posts: 456
Location: The Netherlands

PostPosted: Thu Jul 22, 2010 5:30 am    Post subject: Reply with quote

iPromise wrote:
I port forwarded port: 2300 TCP/UDP, I try to connect and I still get an error.

You should bind to the internal ip that the port is forwarded to, not the external ip.
Back to top
View user's profile Send private message
iPromise
Grandmaster Cheater
Reputation: -1

Joined: 27 Jun 2009
Posts: 529
Location: Canada

PostPosted: Sat Jul 24, 2010 1:59 pm    Post subject: Reply with quote

So when somebody tries to connect, will they use my internal or external ip address, i'm guessing external right?
Back to top
View user's profile Send private message MSN Messenger
SFP+
Comp. talk moderator
Reputation: 26

Joined: 02 May 2007
Posts: 1228
Location: Sweden

PostPosted: Sat Jul 31, 2010 8:44 am    Post subject: Reply with quote

iPromise wrote:
So when somebody tries to connect, will they use my internal or external ip address, i'm guessing external right?
external
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> General programming All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites