Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/network/src/lib/network/network_socket.cc @ 5625

Last change on this file since 5625 was 5625, checked in by rennerc, 18 years ago

network_socket: added new mutex

File size: 6.5 KB
Line 
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, David Hasenfratz
13   co-programmer:
14*/
15
16
17
18/* this is for debug output. It just says, that all calls to PRINT() belong to the DEBUG_MODULE_NETWORK module
19   For more information refere to https://www.orxonox.net/cgi-bin/trac.cgi/wiki/DebugOutput
20*/
21#define DEBUG_MODULE_NETWORK
22
23
24/* include your own header */
25#include "network_socket.h"
26
27/* header for debug output */
28#include "debug.h"
29
30
31/**
32 * Default constructor
33 */
34NetworkSocket::NetworkSocket()
35{
36  /* set the class id for the base object */
37  this->setClassID(CL_NETWORK_SOCKET, "NetworkSocket");
38
39  tcpSocket = NULL;
40  bufferlength = 0;
41
42  mutex = SDL_CreateMutex();
43  socketmutex = SDL_CreateMutex();
44  terminateThread = false;
45
46  /* Init SDL_net */
47  //NOTE: do we need to call SDLNet_Init for all instances?
48  if(SDLNet_Init()==-1)
49  {
50    PRINTF(1)("SDLNet_Init: %s\n", SDLNet_GetError());
51    return;
52  }
53  else
54    PRINTF(5)("SDL_net initialized\n");
55
56  PRINTF(0)("NetworkSocket created\n");
57
58}
59
60/**
61 * Default destructor
62 */
63NetworkSocket::~ NetworkSocket( )
64{
65  /* Quit SDL_net */
66  // NOTE: what if other instances of NetworkSocket running?
67  SDLNet_Quit();
68  PRINTF(5)("SDL_net shutdown\n");
69
70  SDL_DestroyMutex(mutex);
71  SDL_DestroyMutex(socketmutex);
72}
73
74/**
75 * This function establishes a TCP/UDP connection to a given server (function argument).
76 * It is called by the NetworkStream. It creates a TCP/UDP socket for the connection.
77 * @param ip
78 * @param port
79 */
80void NetworkSocket::connectToServer(IPaddress ip, unsigned int port)
81{
82  //check if not already connected or listening
83  if (tcpSocket)
84  {
85    PRINTF(1)("NetworkSocket::listen: tcpSocket!=NULL! maybe you already called listen or connectToServer or did not call disconnectServer()!");
86  }
87
88  /* Connect to the host and port contained in ip using a TCP connection. */
89  tcpSocket = SDLNet_TCP_Open(&ip);
90  if(!tcpSocket)
91  {
92    PRINTF(1)("SDLNet_TCP_Open: %s\n", SDLNet_GetError());
93    return;
94  }
95
96  SDL_CreateThread(thread_read, (void*)this);
97}
98
99/**
100 * Tells the NetworkSocket to listen on a specific port for incoming connections.
101 * NetworkSocket::writeBytes(...) will have no effect until there is a valuable connection.
102 * @param port
103 */
104void NetworkSocket::listen(unsigned int port)
105{
106  //check if not already connected or listening
107  if (tcpSocket)
108  {
109    PRINTF(1)("NetworkSocket::listen: tcpSocket!=NULL! maybe you already called listen or connectToServer or did not call disconnectServer()!\n");
110    return;
111  }
112
113  IPaddress ip;
114
115  if (SDLNet_ResolveHost(&ip, NULL, port)==-1)
116  {
117    PRINTF(1)("SDLNet_ResolveHost: %s\n", SDLNet_GetError());
118    return;
119  }
120
121  tcpSocket = SDLNet_TCP_Open(&ip);
122
123  if (!tcpSocket)
124  {
125    PRINTF(1)("SDLNet_TCP_Open: %s\n", SDLNet_GetError());
126    return;
127  }
128
129  SDL_CreateThread(thread_listen, (void*)this);
130}
131
132/**
133 * DTears down a TCP/UDP connection.
134 */
135void NetworkSocket::disconnectServer( )
136{
137  terminateThread = true;
138  /* Close the connection */
139
140  SDL_mutexP(socketmutex);
141  SDLNet_TCP_Close(tcpSocket);
142  tcpSocket = NULL;
143  SDL_mutexV(socketmutex);
144
145}
146
147
148/**
149 * This function writes some bytes (data) to the network connection (if the connection is already
150 * estabilhed) otherwise it just does nothing (silently discarding the data). And writes some
151 * warnings
152 * @param data: pointer to the data to send
153 * @param length: n bytes to send
154 * @return the number successfully written bytes
155 */
156int NetworkSocket::writeBytes(byte * data, int length)
157{
158  SDL_mutexP(socketmutex);
159
160  if (!tcpSocket || data==NULL)
161    return 0;
162
163  int res = SDLNet_TCP_Send(tcpSocket, data, length);
164
165  SDL_mutexV(socketmutex);
166
167  if (res<length)
168  {
169    PRINTF(1)("SDLNet_TCP_Send: %s\n", SDLNet_GetError());
170    return res;
171  }
172}
173
174/**
175 * Reads in the bytes from the network interface and passes it to the NetworkStream.
176 * This function must internaly be implemented/connected as a thread, since the read
177 * functions of many network libraries are blocking an would therefore block the whole
178 * program.
179 * From outside, the thread shouldn't be accessible at all.
180 * @param data: pointer to memory, big enough to store length bytes
181 * @param length: n bytes to read
182 * @return the number successfully read bytes. -1 on error. may be less than length!
183 */
184int NetworkSocket::readBytes(byte * data, int length)
185{
186  if (data==NULL)
187    return 0;
188
189  int nbytes = (length<bufferlength) ? length : bufferlength;
190
191  // just in case ...
192  if (nbytes<0)
193    return -1;
194
195  if (nbytes==0)
196      return 0;
197
198  SDL_mutexP(mutex);
199
200  memcpy(data, buf, nbytes);
201
202  //important: use memmove because the memory areas may overlap
203  memmove(buf, buf+nbytes, bufferlength-nbytes);
204  bufferlength -= nbytes;
205
206  SDL_mutexV(mutex);
207
208  return nbytes;
209}
210
211/**
212 * used to create a thread to listen
213 * will call thrad_read when established connection
214 * @param data: pointer to NetwortSocket
215 */
216int NetworkSocket::thread_listen( void * data )
217{
218  NetworkSocket * self = (NetworkSocket*)data;
219  TCPsocket tempsocket;
220
221  tempsocket = SDLNet_TCP_Accept(self->tcpSocket);
222
223  SDL_mutexP(self->socketmutex);
224  SDLNet_TCP_Close(self->tcpSocket);
225  self->tcpSocket = NULL;
226
227  if (!tempsocket)
228  {
229    PRINTF(1)("SDLNet_TCP_Accept: %s\n", SDLNet_GetError());
230    SDL_mutexV(self->socketmutex);
231    return -1;
232  }
233
234  self->tcpSocket = tempsocket;
235
236  SDL_mutexV(self->socketmutex);
237
238  return thread_read(data);
239}
240
241/**
242 * used to create a thread to read from socket
243 * @param data: pointer to NetworkSocket
244 */
245int NetworkSocket::thread_read( void * data )
246{
247  int nbytesread = 0;
248  int nbytestoread = 0;
249  char buffer[_LOCAL_BUFFER_SIZE];
250  NetworkSocket * self = (NetworkSocket*)data;
251
252  while (!self->terminateThread)
253  {
254#define min(a,b) (a<b)?a:b
255    nbytestoread = min(_INCOMING_BUFFER_SIZE - self->bufferlength, _LOCAL_BUFFER_SIZE);
256
257    nbytesread = SDLNet_TCP_Recv(self->tcpSocket, buffer, nbytestoread);
258
259    SDL_mutexP(self->mutex);
260
261    if (nbytesread<=0)
262    {
263      PRINTF(1)("SDLNet_TCP_Recv: %s\n", SDLNet_GetError());
264
265      SDL_mutexP(self->socketmutex);
266
267      SDLNet_TCP_Close(self->tcpSocket);
268      self->tcpSocket = NULL;
269
270      SDL_mutexV(self->socketmutex);
271      SDL_mutexV(self->mutex);
272      return -1;
273    }
274
275    memcpy(self->buf+self->bufferlength, buffer, nbytesread);
276    self->bufferlength += nbytesread;
277
278    SDL_mutexV(self->mutex);
279  }
280
281  return 0;
282}
283
284
Note: See TracBrowser for help on using the repository browser.