src/SAL_network.cpp

00001 /*
00002     SAL - Simple Application Library
00003     Copyright (C) 2006-2006 Kronon
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Lesser General Public
00007     License as published by the Free Software Foundation; either
00008     version 2.1 of the License, or (at your option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Lesser General Public License for more details.
00014 
00015     You should have received a copy of the GNU Lesser General Public
00016     License along with this library; if not, write to the Free Software
00017     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018 
00019     Kronon
00020     kronon88@users.sourceforge.net
00021 */
00022 
00023 //SAL network functionality
00024 //Created by Kronon
00025 
00026 //Doxy gen information
00027 
00032 #include "SAL_network.h"
00033  
00041 int SAL_start_network()
00042 {
00043         //Start SDLNet library
00044         if(SDLNet_Init()==-1)
00045         {
00046                 salError("Couldn't start network.", SDLNet_GetError());
00047                 exit(2);
00048         }
00049         return 0;
00050 }
00051 
00059 int SAL_stop_network()
00060 {
00061         //Stop threads
00062         for(SAL_struct.internal.event.network_listeners.setLoopBegin(); SAL_struct.internal.event.network_listeners.inLoop(); )
00063         {
00064                 //Free thread
00065                 SDL_WaitThread(SAL_struct.internal.event.network_listeners.getLoopEntry()->thread, NULL);
00066                 //Free socket set
00067                 SDLNet_FreeSocketSet(SAL_struct.internal.event.network_listeners.getLoopEntry()->socketSet);
00068                 //Free all sockets in network listener
00069                 for(SAL_struct.internal.event.network_listeners.getLoopEntry()->sockets.setLoopBegin(); SAL_struct.internal.event.network_listeners.getLoopEntry()->sockets.inLoop(); )
00070                 {
00071                         SDLNet_UDP_Close(SAL_struct.internal.event.network_listeners.getLoopEntry()->sockets.getLoopEntry());
00072                 }
00073         }
00074         
00075         SDLNet_Quit();
00076         return 0;
00077 }
00078 
00085 int addUdpInputSocket(Uint16 portNr)
00086 {
00087         if(SAL_struct.internal.event.network_listeners.getSize() == 0)
00088         {
00089                 //Add first network listener thread
00090                 SAL_struct.internal.event.last_network_listener = new SAL_network_listener;
00091                 SAL_struct.internal.event.last_network_listener->socketSet = SDLNet_AllocSocketSet(SAL_struct.setting.common.max_con_network_listener);
00092                 SAL_struct.internal.event.network_listeners.append(SAL_struct.internal.event.last_network_listener);
00093                 SAL_struct.internal.event.last_network_listener->thread = SDL_CreateThread(SAL_network_listener_thread, NULL);
00094                 printf("0 listeners adding 1\n");
00095         }
00096         else if(SAL_struct.internal.event.last_network_listener->sockets.getSize() < SAL_struct.setting.common.max_con_network_listener)
00097         {
00098                 //Add another network listener thread
00099                 SAL_struct.internal.event.last_network_listener = new SAL_network_listener;
00100                 SAL_struct.internal.event.last_network_listener->socketSet = SDLNet_AllocSocketSet(SAL_struct.setting.common.max_con_network_listener);
00101                 SAL_struct.internal.event.network_listeners.append(SAL_struct.internal.event.last_network_listener);
00102                 SAL_struct.internal.event.last_network_listener->thread = SDL_CreateThread(SAL_network_listener_thread, NULL);
00103                 printf("Multi listeners adding 1\n");
00104         }
00105         //Create and safe socket
00106         UDPsocket socket = SDLNet_UDP_Open(portNr);
00107         SAL_struct.internal.event.last_network_listener->sockets.append(socket);
00108         
00109         //Add socket to listening socket set
00110         if(SDLNet_UDP_AddSocket(SAL_struct.internal.event.last_network_listener->socketSet, socket) == -1)
00111         {
00112                 salError("Failed to sign socket to socket set");
00113         }
00114         
00115         return 0;
00116 }
00117 
00124 int addUdpOutputSocket(Uint16 portNr)
00125 {
00126         UDPsocket socket = NULL;
00127         socket = SDLNet_UDP_Open(portNr);
00128         if(!socket)                                                                                                                                     //Couldn't open specified socket
00129         {
00130                 socket = SDLNet_UDP_Open(0);                                                                                    //Check if it helps to open an random socket instead
00131                 if(!socket)
00132                 {
00133                         salError("Couldn open any socket");
00134                         return -1;
00135                 }
00136                 else
00137                         salError("Couldn't open socket, opend random socket instead");
00138         }
00139         SAL_struct.internal.event.socketsOut.append(socket);
00140         return 0;
00141 }
00142 
00153 int sendUdpMessage(const char* message, Uint16 mesLen, IPaddress *addresses, Uint8 numIp, UDPsocket socket)
00154 {
00155         UDPpacket *packet =     SDLNet_AllocPacket(mesLen);                             //Create new packet thats used over and over again
00156         int numSent;
00157         packet->len = mesLen;
00158         packet->data = (Uint8 *)message;
00159         
00160         if(numIp == 0)                                                                                          //Send message to one ip address
00161         {
00162                 packet->address = *addresses;                                                   //Set recipient NOTE:does this work?
00163                 numSent = SDLNet_UDP_Send(socket, -1, packet);                  //Send message
00164                 if(!numSent)
00165                 {
00166                         salError("Packet couldn't be send");
00167                         return -1;
00168                 }
00169         }
00170         else                                                                                                            //Send message to enlisted ip addresses
00171         {
00172                 for(int i = 0; i< numIp; i++)                                                   //Loop truh enlisted addresses
00173                 {
00174                         packet->address = *addresses;                                           //NOTE:Does this work?
00175                         numSent = SDLNet_UDP_Send(socket, -1, packet);
00176                         if(!numSent)
00177                         {
00178                                 salError("Packet couldn't be send");
00179                                 return -1;
00180                         }
00181                         addresses++;                                                                                    //Select next address
00182                 }
00183         }
00184         return 0;
00185 }
00186 
00194 int SAL_network_listener_thread(void * unused)
00195 {
00196         UDPpacket *packet;
00197         SAL_network_listener *listener;                                                                                         //This network listener
00198         int numRecv = 0, numWaiting = 0;                                                                                        //Number of connections receved
00199         listener = SAL_struct.internal.event.last_network_listener;
00200          
00201         packet = SDLNet_AllocPacket(SAL_MAX_PACKET_SIZE);                                                       //Create new packet thats used over and over again
00202         if(!packet)
00203         {
00204                 salError("Failed to create packet",SDLNet_GetError());
00205         }
00206         
00207         while(SAL_struct.internal.checks.alive)
00208         {
00209                 //Wait for network activity or network time out
00210                 numWaiting = SDLNet_CheckSockets(listener->socketSet, SAL_struct.setting.common.network_time_out_time);
00211                 if(numWaiting==-1)
00212                 {
00213                         salError("Network error while waiting for package");
00214                 }
00215                 else if(numWaiting == 0)                                                                                                //Time out
00216                 {
00217                         if(SAL_struct.setting.common.network_time_out_function)
00218                         {
00219                                 SAL_struct.setting.common.network_time_out_function();
00220                         }
00221                         continue;
00222                 }
00223                 
00224                 for(listener->sockets.setLoopBegin(); listener->sockets.inLoop(); )
00225                 {
00226                         numRecv=SDLNet_UDP_Recv(listener->sockets.getLoopEntry(), packet);      //Fetch new packet
00227                         
00228                         //Message whas receved on other port
00229                         if(numRecv == 0)
00230                         {
00231 //                              printf("message goes to other\n");
00232                                 continue;
00233                         }
00234                         //Port whas caught in an error
00235                         if(numRecv == -1)
00236                         {
00237                                 salError("Network error while retreaving packet");
00238                         }
00239                         else
00240                         {
00241                                 //TODO:Fetch data using network byte order
00242                                 
00243                                 //Get space for incoming data
00244                                 Uint32 *data = (Uint32 *)malloc(sizeof(char) * packet->len);
00245                                 //Translate incomming message to correct Endian and store into memory
00246                                 Uint32 *tData = (Uint32 *)packet->data;                                                 //32 bits is faster then 8 bits:)
00247                                 for(Uint16 i = 0; i < packet->len/4; i++)
00248                                 {
00249                                         data[i] = tData[i];                                                                                     //Copy data
00250                                 }
00251                                 
00252 #ifdef SAL_DEBUG
00253                                 char * cData = (char *) data;                                                                   //To be able to read the data as chars
00254                                 for(Uint16 i = 0; i < packet->len; i++)
00255                                 {
00256                                         printf("%c",(char) cData[i]);
00257                                 }
00258                                 
00259                                 printf("\n");
00260 #endif
00261                                 //TODO: run  event handler
00262                         }
00263                 }
00264         }
00265         SDLNet_FreePacket(packet);
00266         return 0;
00267 }
00268 
00275 int salSetNetworkHandler(int (*network_handler)(char *message, IPaddress *address))
00276 {
00277         SAL_struct.internal.event.network_handler.handler = network_handler;
00278         return 0;
00279 }