00001
00002
00003
00004
00005
00006
00007
00008 #include "WOscTcpHandler.h"
00009
00010
00011
00012
00013
00014
00015
00016 #if OS_IS_LINUX == 1 || OS_IS_MACOSX == 1 || OS_IS_CYGWIN == 1
00017
00018 #include <fcntl.h>
00019 #include <sys/socket.h>
00020
00021
00022 #if !defined(MSG_NOSIGNAL) && OS_IS_MACOSX == 1
00023 # define MSG_NOSIGNAL SO_NOSIGPIPE
00024 #endif
00025
00026
00027 void*
00028 wosc_tcp_handler_rx_thread(void* argument)
00029 {
00030 WOscTcpHandler* handler = static_cast<WOscTcpHandler*>(argument);
00031 handler->ReceiveThread();
00032 pthread_exit(NULL);
00033 }
00034
00035 static int
00036 wosc_send_over_socket(int socket, const char* buffer, int count)
00037 {
00038 int nSent = 0;
00039 for ( int tmp; (count - nSent ) > 0; nSent += tmp) {
00040 tmp = send(socket, buffer + nSent, count - nSent, MSG_NOSIGNAL);
00041 if ( tmp <= 0 )
00042 return -1;
00043 }
00044 return nSent;
00045 }
00046
00047 template<class TYPE> class WOscAutoArray
00048 {
00049 public:
00050 WOscAutoArray(TYPE* array) : m_array(array) { }
00051 virtual ~WOscAutoArray() { delete [] m_array; }
00052 TYPE* operator &() { return m_array; }
00053 operator TYPE*() { return m_array; }
00054 private:
00055 TYPE* m_array;
00056 };
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 WOscTcpHandler::WOscTcpHandler(bool threading)
00069 {
00070 m_receptionThreadID = 0;
00071 m_socketID = -1;
00072 pthread_mutex_init(&m_mutexTx, NULL);
00073 m_threading = threading;
00074 }
00075
00076 WOscTcpHandler::~WOscTcpHandler()
00077 {
00078 pthread_mutex_destroy(&m_mutexTx);
00079
00080
00081 }
00082
00083 const char*
00084 WOscTcpHandler::GetErrStr(Error err)
00085 {
00086 switch ( err ) {
00087 case WOS_ERR_NO_ERROR: return "No error.";
00088 case WOS_ERR_ALREADY_RUNNING: return "Seems that a reception thread is already running. You have to disconnect first.";
00089 case WOS_ERR_ALREADY_CONNECTED: return "Seems that we're already connected";
00090 case WOS_ERR_SOCKET_CREATE: return "Socket creation failed.";
00091 case WOS_ERR_SOCKET_CONNECT: return "Socket connect failed.";
00092 case WOS_ERR_CREATE_RX_THREAD: return "Creation of receive thread failed.";
00093 case WOS_ERR_NO_SOCKET: return "Socket not connected.";
00094 case WOS_ERR_CONNECTION_LOST: return "Socket connection lost.";
00095 case WOS_ERR_DISCONNECTED: return "Trying to close an already closed socket.";
00096 case WOS_ERR_CONNECTION_CLOSED: return "Tried to receive with "
00097 "WOscTcpClient::NetworkReceive() from a connection which has been "
00098 "closed.";
00099 case WOS_ERR_CONNECTION_FAILURE: return "Receiving from WOscTcpClient::NetworkReceive() failed.";
00100 case WOS_ERR_NOT_WHEN_THREADING: return "The select/polling receive "
00101 "function can only be used with threading disabled.";
00102 case WOS_ERR_CAN_NOT_SET_NONBLOCKING: return "Can not set socket into non blocking mode.";
00103 default: return "Unknown error.";
00104 }
00105 }
00106
00107
00108 WOscTcpHandler::Error
00109 WOscTcpHandler::NetworkSend(const char* data, int dataLen)
00110 {
00111 pthread_mutex_lock(&m_mutexTx);
00112 if ( m_socketID < 0 ) {
00113 pthread_mutex_unlock(&m_mutexTx);
00114 return WOS_ERR_NO_SOCKET;
00115 }
00116
00117 int len = htonl(dataLen);
00118 len = wosc_send_over_socket(m_socketID, (const char*)&len, sizeof(len));
00119 if ( len <= 0 ) {
00120 pthread_mutex_unlock(&m_mutexTx);
00121 return WOS_ERR_CONNECTION_LOST;
00122 }
00123 len = wosc_send_over_socket(m_socketID, data, dataLen);
00124 if ( len <= 0 ) {
00125 pthread_mutex_unlock(&m_mutexTx);
00126 return WOS_ERR_CONNECTION_LOST;
00127 }
00128 pthread_mutex_unlock(&m_mutexTx);
00129 return WOS_ERR_NO_ERROR;
00130 }
00131
00132 void
00133 WOscTcpHandler::NetworkSend(const char* data, int dataLen,
00134 const WOscNetReturn* networkReturnAddress)
00135 {
00136 NetworkSend(data, dataLen);
00137 }
00138 void
00139 WOscTcpHandler::ReceiveThread()
00140 {
00141 while ( true ) {
00142 Error err = NetworkReceiveInternal();
00143 if ( err == WOS_ERR_NO_ERROR ) {
00144 continue;
00145 } else if ( err == WOS_ERR_CONNECTION_CLOSED ) {
00146 break;
00147 } else if ( err == WOS_ERR_CONNECTION_FAILURE ) {
00148 break;
00149 }
00150 }
00151 }
00152
00153 WOscTcpHandler::Error
00154 WOscTcpHandler::NetworkReceive()
00155 {
00156 if ( m_threading )
00157 return WOS_ERR_NOT_WHEN_THREADING;
00158 return NetworkReceiveInternal();
00159 }
00160
00161 WOscTcpHandler::Error
00162 WOscTcpHandler::Start(int socketID, const TheNetReturnAddress& peer)
00163 {
00164 if (socketID < 0)
00165 return WOS_ERR_INVALID_SOCKET;
00166 if ( m_socketID >= 0 )
00167 return WOS_ERR_ALREADY_CONNECTED;
00168
00169 if ( m_receptionThreadID > 0 )
00170 return WOS_ERR_ALREADY_RUNNING;
00171
00172 m_socketID = socketID;
00173 m_selectState.Init();
00174 m_peer = peer;
00175
00176 if ( m_threading ) {
00177
00178 int ret = pthread_create(&m_receptionThreadID, NULL, wosc_tcp_handler_rx_thread, this);
00179 if ( ret ) {
00180
00181 m_socketID = -1;
00182 m_receptionThreadID = 0;
00183 return WOS_ERR_CREATE_RX_THREAD;
00184 }
00185 } else {
00186
00187
00188 if (fcntl(m_socketID, F_SETFL, fcntl(m_socketID, F_GETFL) | O_NONBLOCK) < 0) {
00189
00190 m_socketID = -1;
00191 return WOS_ERR_CAN_NOT_SET_NONBLOCKING;
00192 }
00193
00194 }
00195 return WOS_ERR_NO_ERROR;
00196
00197 }
00198
00199
00200
00201
00202 WOscTcpHandler::Error
00203 WOscTcpHandler::Stop()
00204 {
00205
00206 if ( m_threading && m_receptionThreadID == 0 )
00207 return WOS_ERR_ALREADY_CLOSED;
00208
00209
00210 if ( m_socketID < 0 )
00211 return WOS_ERR_DISCONNECTED;
00212
00213
00214 if ( m_threading ) {
00215
00216 void* threadReturn = NULL;
00217 int ret = pthread_cancel(m_receptionThreadID);
00218 if ( ret ) {
00219
00220 }
00221 ret = pthread_join(m_receptionThreadID, &threadReturn);
00222 if ( ret ) {
00223
00224 }
00225 m_receptionThreadID = 0;
00226 }
00227 m_socketID = -1;
00228
00229
00230 return WOS_ERR_NO_ERROR;
00231 }
00232
00233 WOscTcpHandler::Error
00234 WOscTcpHandler::NetworkReceiveInternal()
00235 {
00236 char* rxBuf;
00237 int rxCount;
00238 if ( m_selectState.m_isRxPacketLen ) {
00239 rxBuf = (char*)&m_selectState.m_packetLen + m_selectState.m_nReceived;
00240 rxCount = sizeof(m_selectState.m_packetLen) - m_selectState.m_nReceived;
00241 } else {
00242 rxBuf = m_selectState.m_packetData;
00243 rxCount = m_selectState.m_packetLen - m_selectState.m_nReceived;
00244 }
00245
00246 int nRecv = recv(m_socketID, rxBuf, rxCount, 0);
00247
00248 if ( nRecv == 0 ) {
00249
00250 return WOS_ERR_CONNECTION_CLOSED;
00251 } else if ( nRecv < 0 ) {
00252
00253 return WOS_ERR_CONNECTION_FAILURE;
00254 } else {
00255 m_selectState.m_nReceived += nRecv;
00256 }
00257
00258
00259 if ( m_selectState.m_isRxPacketLen && m_selectState.m_nReceived == sizeof(m_selectState.m_packetLen) ) {
00260 m_selectState.m_packetLen = ntohl(m_selectState.m_packetLen);
00261 m_selectState.m_isRxPacketLen = false;
00262 delete [] m_selectState.m_packetData;
00263 m_selectState.m_packetData = new char[m_selectState.m_packetLen];
00264 m_selectState.m_nReceived = 0;
00265 }
00266
00267 else if ( !m_selectState.m_isRxPacketLen && m_selectState.m_nReceived == m_selectState.m_packetLen) {
00268 m_selectState.m_isRxPacketLen = true;
00269 WOscReceiver::NetworkReceive(m_selectState.m_packetData, m_selectState.m_packetLen, new TheNetReturnAddress(m_peer));
00270 m_selectState.m_nReceived = 0;
00271 }
00272 return WOS_ERR_NO_ERROR;
00273 }
00274
00275 #elif OS_IS_WIN32 == 1
00276
00277
00278
00279
00280
00281 # warning "WOscTcpHandler not supported on this platform"
00282 #endif