| [7540] | 1 | /* | 
|---|
|  | 2 | orxonox - the future of 3D-vertical-scrollers | 
|---|
|  | 3 |  | 
|---|
|  | 4 | Copyright (C) 2004 orx | 
|---|
|  | 5 |  | 
|---|
|  | 6 | This program is free software; you can redistribute it and/or modify | 
|---|
|  | 7 | it under the terms of the GNU General Public License as published by | 
|---|
|  | 8 | the Free Software Foundation; either version 2, or (at your option) | 
|---|
|  | 9 | any later version. | 
|---|
|  | 10 |  | 
|---|
|  | 11 | ### File Specific: | 
|---|
|  | 12 | main-programmer: Christoph Renner | 
|---|
|  | 13 | co-programmer: | 
|---|
|  | 14 | */ | 
|---|
|  | 15 |  | 
|---|
|  | 16 | #include "udp_socket.h" | 
|---|
|  | 17 | #include "udp_server_socket.h" | 
|---|
| [8362] | 18 | #include "debug.h" | 
|---|
| [7540] | 19 |  | 
|---|
|  | 20 |  | 
|---|
|  | 21 | void UdpSocket::init( ) | 
|---|
|  | 22 | { | 
|---|
| [7541] | 23 | //TODO setClassId | 
|---|
| [7540] | 24 | this->serverSocket = NULL; | 
|---|
|  | 25 | this->socket = NULL; | 
|---|
|  | 26 | this->packet = NULL; | 
|---|
|  | 27 | } | 
|---|
|  | 28 |  | 
|---|
|  | 29 |  | 
|---|
|  | 30 | /** | 
|---|
|  | 31 | * constructor - connects to give host | 
|---|
|  | 32 | * @param host host | 
|---|
|  | 33 | * @param port port | 
|---|
|  | 34 | */ | 
|---|
|  | 35 | UdpSocket::UdpSocket( std::string host, int port ) | 
|---|
|  | 36 | { | 
|---|
|  | 37 | init(); | 
|---|
|  | 38 | this->packet = SDLNet_AllocPacket( UDP_PACKET_SIZE ); | 
|---|
| [8362] | 39 |  | 
|---|
| [7613] | 40 | assert( this->packet ); | 
|---|
| [8362] | 41 |  | 
|---|
| [7613] | 42 | memset( packet->data, 0, UDP_PACKET_SIZE ); | 
|---|
|  | 43 | PRINTF(0)("PACKET DATA: %x\n", packet->data); | 
|---|
| [8362] | 44 |  | 
|---|
| [7540] | 45 | this->connectToServer( host, port ); | 
|---|
|  | 46 | } | 
|---|
|  | 47 |  | 
|---|
|  | 48 | /** | 
|---|
|  | 49 | * default constructor. use this one if you want to call connecttoServer | 
|---|
|  | 50 | */ | 
|---|
|  | 51 | UdpSocket::UdpSocket( ) | 
|---|
|  | 52 | { | 
|---|
|  | 53 | this->init(); | 
|---|
|  | 54 | this->packet = SDLNet_AllocPacket( UDP_PACKET_SIZE ); | 
|---|
| [8362] | 55 |  | 
|---|
| [7540] | 56 | if ( !packet ) | 
|---|
|  | 57 | { | 
|---|
|  | 58 | PRINTF(1)("SDLNet_AllocPacket: %s\n", SDLNet_GetError()); | 
|---|
| [8362] | 59 |  | 
|---|
| [7540] | 60 | assert( false ); | 
|---|
|  | 61 | bOk = false; | 
|---|
|  | 62 | } | 
|---|
| [8362] | 63 |  | 
|---|
| [7540] | 64 | } | 
|---|
|  | 65 |  | 
|---|
|  | 66 | /** | 
|---|
|  | 67 | * constructor. used by UdpServerSocket | 
|---|
|  | 68 | * @param serverSocket pointer to serverSocket | 
|---|
|  | 69 | * @param ip client's ip address | 
|---|
|  | 70 | * @param userId userid used by serverSocket | 
|---|
|  | 71 | */ | 
|---|
|  | 72 | UdpSocket::UdpSocket( UdpServerSocket * serverSocket, IPaddress ip, int userId ) | 
|---|
|  | 73 | { | 
|---|
|  | 74 | this->init(); | 
|---|
|  | 75 | this->serverSocket = serverSocket; | 
|---|
| [7556] | 76 | this->userId = userId; | 
|---|
| [7540] | 77 | } | 
|---|
|  | 78 |  | 
|---|
|  | 79 | /** | 
|---|
|  | 80 | * destructor | 
|---|
|  | 81 | */ | 
|---|
| [7556] | 82 | UdpSocket::~UdpSocket( ) | 
|---|
| [7540] | 83 | { | 
|---|
| [8228] | 84 | this->disconnectServer(); | 
|---|
| [8362] | 85 |  | 
|---|
| [7540] | 86 | if ( serverSocket ) | 
|---|
|  | 87 | serverSocket->removeUser( userId ); | 
|---|
| [8228] | 88 |  | 
|---|
| [7556] | 89 | if ( this->packet ) | 
|---|
|  | 90 | SDLNet_FreePacket( this->packet ); | 
|---|
| [8362] | 91 |  | 
|---|
| [7556] | 92 | if ( socket ) | 
|---|
|  | 93 | SDLNet_UDP_Close( socket ); | 
|---|
| [7540] | 94 | } | 
|---|
|  | 95 |  | 
|---|
|  | 96 | /** | 
|---|
|  | 97 | * connect to server | 
|---|
|  | 98 | * @param host host name | 
|---|
|  | 99 | * @param port port number | 
|---|
|  | 100 | */ | 
|---|
|  | 101 | void UdpSocket::connectToServer( std::string host, int port ) | 
|---|
|  | 102 | { | 
|---|
|  | 103 | assert( serverSocket == NULL ); | 
|---|
| [8362] | 104 |  | 
|---|
| [7540] | 105 | IPaddress ip; | 
|---|
| [8362] | 106 |  | 
|---|
| [7570] | 107 | PRINTF(0)("connect to server %s on port %d\n", host.c_str(), port); | 
|---|
| [8362] | 108 |  | 
|---|
| [7540] | 109 | if ( SDLNet_ResolveHost( &ip, host.c_str(), port ) != 0 ) | 
|---|
|  | 110 | { | 
|---|
|  | 111 | PRINTF(1)("SDLNet_ResolveHost: %s\n", SDLNet_GetError() ); | 
|---|
|  | 112 | bOk = false; | 
|---|
|  | 113 | return; | 
|---|
|  | 114 | } | 
|---|
| [8362] | 115 |  | 
|---|
| [7540] | 116 | socket = SDLNet_UDP_Open(0); | 
|---|
|  | 117 | if ( !socket ) | 
|---|
|  | 118 | { | 
|---|
|  | 119 | PRINTF(1)("SDLNet_UDP_Open: %s\n", SDLNet_GetError() ); | 
|---|
|  | 120 | bOk = false; | 
|---|
|  | 121 | return; | 
|---|
|  | 122 | } | 
|---|
| [8362] | 123 |  | 
|---|
| [7553] | 124 | int channel = SDLNet_UDP_Bind(socket, 1, &ip); | 
|---|
| [8362] | 125 | if ( channel == -1 ) | 
|---|
| [7540] | 126 | { | 
|---|
| [7872] | 127 | PRINTF(1)("SDLNet_UDP_Bind: %s\n", SDLNet_GetError()); | 
|---|
| [7540] | 128 | bOk = false; | 
|---|
|  | 129 | return; | 
|---|
|  | 130 | } | 
|---|
|  | 131 | } | 
|---|
|  | 132 |  | 
|---|
|  | 133 | /** | 
|---|
|  | 134 | * disconnect from server | 
|---|
|  | 135 | */ | 
|---|
|  | 136 | void UdpSocket::disconnectServer( ) | 
|---|
|  | 137 | { | 
|---|
| [8228] | 138 | PRINTF(0)("disconnect\n"); | 
|---|
|  | 139 | writePacket( NULL, 0 ); | 
|---|
| [7540] | 140 | SDLNet_UDP_Unbind( socket, -1 ); | 
|---|
|  | 141 | SDLNet_UDP_Close( socket ); | 
|---|
| [7565] | 142 | bOk = false; | 
|---|
| [7540] | 143 | socket = NULL; | 
|---|
|  | 144 | } | 
|---|
|  | 145 |  | 
|---|
|  | 146 | /** | 
|---|
|  | 147 | * send one packet to other host | 
|---|
|  | 148 | * @param data pointer to data which will be sent | 
|---|
|  | 149 | * @param length length of data | 
|---|
|  | 150 | * @return true on success | 
|---|
|  | 151 | */ | 
|---|
|  | 152 | bool UdpSocket::writePacket( byte * data, int length ) | 
|---|
|  | 153 | { | 
|---|
|  | 154 | if ( serverSocket ) | 
|---|
|  | 155 | { | 
|---|
|  | 156 | NetworkPacket networkPacket; | 
|---|
|  | 157 | networkPacket.length = length; | 
|---|
|  | 158 | networkPacket.data = data; | 
|---|
|  | 159 | if ( !serverSocket->sendPacket( networkPacket, this->userId ) ) | 
|---|
|  | 160 | { | 
|---|
|  | 161 | bOk = false; | 
|---|
|  | 162 | return false; | 
|---|
|  | 163 | } | 
|---|
|  | 164 | else | 
|---|
|  | 165 | return true; | 
|---|
|  | 166 | } | 
|---|
|  | 167 | else | 
|---|
|  | 168 | { | 
|---|
|  | 169 | assert( length <= packet->maxlen ); | 
|---|
| [8362] | 170 |  | 
|---|
| [7540] | 171 | memcpy( packet->data, data, length ); | 
|---|
|  | 172 | packet->len = length; | 
|---|
| [8362] | 173 |  | 
|---|
| [8228] | 174 | if ( socket && SDLNet_UDP_Send( socket, 1, packet) == 0 ) | 
|---|
| [7540] | 175 | { | 
|---|
|  | 176 | PRINTF(1)("SDLNet_UDP_Send: %s\n", SDLNet_GetError()); | 
|---|
|  | 177 | bOk = false; | 
|---|
|  | 178 | return false; | 
|---|
|  | 179 | } | 
|---|
| [8362] | 180 |  | 
|---|
| [7540] | 181 | return true; | 
|---|
|  | 182 | } | 
|---|
|  | 183 | } | 
|---|
|  | 184 |  | 
|---|
|  | 185 | /** | 
|---|
|  | 186 | * recieve one packet from another host | 
|---|
|  | 187 | * @param data pointer to buffer to copy data into | 
|---|
|  | 188 | * @param maxLength maximal length of buffer | 
|---|
|  | 189 | * @return less than 0 on error, number bytes read else | 
|---|
|  | 190 | */ | 
|---|
|  | 191 | int UdpSocket::readPacket( byte * data, int maxLength ) | 
|---|
|  | 192 | { | 
|---|
| [7565] | 193 | assert( maxLength <= UDP_PACKET_SIZE ); | 
|---|
| [8362] | 194 |  | 
|---|
| [7540] | 195 | if ( serverSocket ) | 
|---|
|  | 196 | { | 
|---|
|  | 197 | NetworkPacket networkPacket = serverSocket->getPacket( this->userId ); | 
|---|
| [8362] | 198 |  | 
|---|
| [8228] | 199 | if ( networkPacket.length == -1 ) | 
|---|
|  | 200 | { | 
|---|
|  | 201 | this->disconnectServer(); | 
|---|
|  | 202 | return 0; | 
|---|
|  | 203 | } | 
|---|
| [8362] | 204 |  | 
|---|
| [7540] | 205 | if ( networkPacket.length > 0 ) | 
|---|
|  | 206 | { | 
|---|
|  | 207 | assert( maxLength > networkPacket.length ); | 
|---|
| [8362] | 208 |  | 
|---|
| [7540] | 209 | memcpy( data, networkPacket.data, networkPacket.length ); | 
|---|
|  | 210 | } | 
|---|
| [8362] | 211 |  | 
|---|
| [7540] | 212 | if ( networkPacket.data ) | 
|---|
|  | 213 | { | 
|---|
| [7556] | 214 | free( networkPacket.data ); | 
|---|
| [7540] | 215 | networkPacket.data = NULL; | 
|---|
|  | 216 | } | 
|---|
| [8362] | 217 |  | 
|---|
| [7540] | 218 | return networkPacket.length; | 
|---|
|  | 219 | } | 
|---|
|  | 220 | else | 
|---|
|  | 221 | { | 
|---|
|  | 222 | int numrecv = SDLNet_UDP_Recv( socket, packet); | 
|---|
| [8362] | 223 | if ( numrecv > 0) | 
|---|
| [7540] | 224 | { | 
|---|
|  | 225 | assert( packet->len <= maxLength ); | 
|---|
| [8362] | 226 |  | 
|---|
| [8228] | 227 | if ( packet->len == 0 ) | 
|---|
|  | 228 | { | 
|---|
|  | 229 | this->disconnectServer(); | 
|---|
|  | 230 | return 0; | 
|---|
|  | 231 | } | 
|---|
| [8362] | 232 |  | 
|---|
| [7540] | 233 | memcpy( data, packet->data, packet->len ); | 
|---|
|  | 234 | return packet->len; | 
|---|
|  | 235 | } | 
|---|
|  | 236 | else if ( numrecv < 0 ) | 
|---|
|  | 237 | { | 
|---|
|  | 238 | PRINTF(1)("SDLNet_UDP_Recv: %s\n", SDLNet_GetError()); | 
|---|
|  | 239 | bOk = false; | 
|---|
|  | 240 | return -1; | 
|---|
|  | 241 | } | 
|---|
|  | 242 | else | 
|---|
|  | 243 | { | 
|---|
|  | 244 | return 0; | 
|---|
|  | 245 | } | 
|---|
|  | 246 | } | 
|---|
| [8362] | 247 |  | 
|---|
| [7540] | 248 | return 0; | 
|---|
|  | 249 | } | 
|---|
|  | 250 |  | 
|---|
|  | 251 |  | 
|---|
|  | 252 |  | 
|---|